在 JavaScript 中异步函数之后运行函数
我正在尝试编写一个运行异步函数的代码,当它完成后,它会运行另一段代码。
我尝试将异步函数放在承诺中(如下面的代码所示)并使用
then
方法,但没有成功。
函数内部发生的事情并不重要,但我还是把它包括在内,以防我弄错了,而它确实发生了......
getData = async(file) =>{
let data = await fetch(file);
data = await data.text();
return(data);
}
getDataAndUsername = async() => {
this.setState({data: JSON.parse(await this.getData("/getData"))});
this.setState({username: await this.getData("/user")});
console.log('done');
}
getDataAndUsername 是我尝试在其他函数之前运行的异步函数。
CheckInDataBase = (username) => {
console.log('checking In DataBase');
this.state.data.forEach((element)=>{
if(element.username === username){
this.setState({exist: true});
}
});
if (!(this.state.exist)){
axios.post('/createUser', {"username": username, "status": "Working"});
this.setState({exist: true});
}
}
这是我尝试在异步函数之后运行的常规函数
这是代码:
new Promise((res) => {
this.getDataAndUsername();
res();
}).then(
this.CheckInDataBase(this.state.username)
)
现在发生的事情是,this.CheckInDatabase 在 getDataAndUsername 完成之前运行。
由于被定义为
async
,您的
getDataAndUsername
已经是一个 Promise,因此无需将其包装在
new Promise()
中。您只需执行以下操作:
this.getDataAndUsername().then( _ => {
this.CheckInDataBase(this.state.username);
})
它应该可以工作。
为什么您的代码一开始就不起作用
您正在用这个创建一个新的承诺:
new Promise((res) => {
this.getDataAndUsername();
res();
}) ...
在那里,您正在调用
this.getDataAndUsername()
,但忽略了它是否解析。该代码将立即调用
res
,因此在
getDataAndUsername
解析之前调用了
checkInDatabase
。
您可以等待
getDataAndUsername
解析:
new Promise((res) => {
return this.getDataAndUsername().then(_ => {res()})
}) ...
重点是使用
then
等待承诺解析,同时添加
return
。
但是,如上所述,没有必要这样做,因为
getDataAndUsername
已经是一个 Promise。
正如我在评论中所写,您更新状态的频率太高了。这是一个异步过程,因此您可能最终会检查或循环遍历旧状态。
我建议您尽可能少地使用
this.setState
,而是在尽可能多的函数中返回值。这样,您就可以拆分功能,而不依赖于 React 的状态。
这是我对您的问题的建议:
class App extends React.PureComponent {
getData = async (file) =>{
let data = await fetch(file);
return await data.text();
};
getDataAndUsername = async () => ({
data: JSON.parse(await this.getData("/getData")),
username: JSON.parse(await this.getData("/user"))
});
checkInDataBase = ({ username, data }) => {
console.log('checking In DataBase');
return !!data.find(element => element.username === username);
};
addUser = async username => await axios.post('/createUser', {"username": username, "status": "Working"});
myCheckFunction = async () => {
const dataAndUsername = await this.getDataAndUsername();
if (dataAndUsername) {
if (!this.checkInDataBase(dataAndUsername)) {
const newUser = await this.addUser(dataAndUsername.username);
dataAndUsername.data.push(newUser);
}
// A single place where you update the state
this.setState({
...dataAndUsername,
exists: true
})
}
}
}
尝试:
this.getDataAndUsername().then((response) => {
/**
* Your code that you want to run after getDataAndUsername
*/
}, (error) => {
/**
* Handle error here
*/
});
或者使用
async/await
:
(async function() {
try {
const dataAndUsername = await this.getDataAndUsername();
/**
* Your code that you want to run after getDataAndUsername
*/
} catch(e) {
/**
* Handle error here
*/
}
})();