你的两个例子之间有一个关键的区别。这取决于他们将如何处理被调用await。我将用简化的术语来表示这两者。
第一个代码块:
const someAsyncOperation = ms => new Promise(res => setTimeout(res, ms, "hello"))
async function foo(){
console.log("start async");
await someAsyncOperation(1500)
.then(res => console.log("do something with result:", res + "world"))
.catch(() => console.error("no error will happen"));
console.log("finish async");
}
async function main() {
console.log("before foo()");
await foo();
console.log("after foo()");
}
main();
结果:
before foo()
start async
do something with result: helloworld
finish async
after foo()
与第二个代码块:
const someAsyncOperation = ms => new Promise(res => setTimeout(res, ms, "hello"))
async function foo(){
console.log("start async");
someAsyncOperation(1500)
.then(res => console.log("do something with result:", res + "world"))
.catch(() => console.error("no error will happen"));
console.log("finish async");
}
async function main() {
console.log("before foo()");
await foo();
console.log("after foo()");
}
main();
结果:
before foo()
start async
finish async
after foo()
do something with result: helloworld
如您所见,两种情况下的操作顺序不同。
- 在第一种情况下,an
await将foo()在继续之前完成整个过程。
- 第二,没有
await,所以someAsyncOperation是火和忘记。您的代码将在执行之前完成,因此您永远不会收到成功或失败的通知。
另外,我必须注意,这仅在您使用await. 如果你不这样做,那么代码将永远不会等待它在任何一种情况下完成。
const someAsyncOperation = ms => new Promise(res => setTimeout(res, ms, "hello"))
async function foo(){
console.log("start async");
await someAsyncOperation(1500)
.then(res => console.log("do something with result:", res + "world"))
.catch(() => console.error("no error will happen"));
console.log("finish async");
}
async function main() {
console.log("before foo()");
foo(); //no await
console.log("after foo()");
}
main();
const someAsyncOperation = ms => new Promise(res => setTimeout(res, ms, "hello"))
async function foo(){
console.log("start async");
someAsyncOperation(1500)
.then(res => console.log("do something with result:", res + "world"))
.catch(() => console.error("no error will happen"));
console.log("finish async");
}
async function main() {
console.log("before foo()");
foo(); //no await
console.log("after foo()");
}
main();
这两个操作本质上是一样的。出现的地方有所不同,"finish async"但这只是因为我添加它是为了清楚地了解如何处理函数。在您的代码中,在 Promise 被触发后您没有其他任何内容,因此不会有任何区别。在这两种情况下foo(),它本身就是一场火灾,然后忘记,因为它没有被等待。因此,您是否等待内部操作都没有关系。
无论如何,没有一个通用的“更好”的方式来使用这些承诺。
有时您可能想要一个火灾并忘记功能,这样您就不必真正等待。举个简单的例子:
showSpinner();
getData()
.then(data => {
hideSpinner();
showData(data);
})
.catch(error => {
hideSpinner();
}
/* do more stuff */
据推测,这是某种非关键数据——我们可以显示或不显示,但我们想移除微调器。
其他时候,您实际上可能希望在继续之前等待并验证操作是否成功。例如:
try {
const user = await registerUser(userInfo);
await processPayment(user);
} catch (error) {
cancelTransaction();
throw new RegistrationAndPaymentError(error);
}
/* do more stuff */
如果注册失败,我们必须抽空休息并避免继续该过程。
您选择哪一个取决于您希望如何处理给定的操作。有些你并不真正关心它们何时完成以及如何完成,其他人可能会阻止进一步的操作。
同样值得澄清的是,每个 async/await 使用都可以通过链接.then()和.catch(). 但是,有时链接很多 Promise 操作不如使用awaits 可读。大多数Promise API 操作也可以使用 async/await 来表达。因此,您选择哪一种通常取决于您喜欢哪一种。通常建议不要混合两种类型的语法 - 如果你这样做不会出错,但如果你坚持其中一种会更清楚。
综上所述,还建议使您的函数await能够进行异步操作。原因是,也许现在你可能不想等待他们完成,但将来你可能会。
使用您的第一段代码await handleChangeSelect()已经强制执行暂停,直到函数完成,所以它基本上没问题。诚然,如果它不混合会更好,await但它仍然没有错。.then().catch()
在不添加函数的情况下对函数完成做出反应的方法await(本质上,只使用promise API),您需要返回内部函数产生的promise。因此,您可以将其更改为:
function handleChangeSelect(value,action){
return getOneOrg(value.label).then(res=>{
const updatedCategory = {...modal, [action.name]:value, categories:[{value:res.ans,label:res.ans}]}
setModal(updatedCategory)
}).catch(err=>console.log(err))
}
这将使对函数完成做出反应成为可能:
const someAsyncOperation = ms => new Promise(res => setTimeout(res, ms, "hello"))
async function foo(){
console.log("start async");
return someAsyncOperation(1500)
.then(res => console.log("do something with result:", res + "world"))
.catch(() => console.error("no error will happen"))
.then(() => console.log("finish async")); //we don't want any code after the async call
//so, further code will be chained as .then()
}
async function main() {
console.log("before foo()");
await foo();
console.log("after foo()");
}
main();