正如它的名字所暗示的那样,await
关键字将导致函数“等待”直到它的承诺在执行下一行之前解决。的重点await
是让代码等到操作完成后再继续。
这与阻塞代码的区别在于,函数外部的世界可以在函数等待异步操作完成时继续执行。
async
并且await
只是承诺之上的语法糖。它们允许您编写看起来很像普通同步代码的代码,即使它在幕后使用了 Promise。如果我们将您的示例翻译为明确适用于承诺的内容,它将看起来像:
function myAsyncFunction() {
return myAPICall('https://jsonplaceholder.typicode.com/posts/1')
.then(function (data) {
let result = 2 + 2;
return data;
})
.catch(function (ex) {
return ex;
});
}
正如我们在此处看到的,该let result = 2 + 2;
行位于.then()
处理程序内部,这意味着它在解决之前不会执行myAPICall()
。使用时也是一样await
。await
只是为你抽象出来.then()
。
要记住的一件事(我认为您正在寻找的重点)是您不必立即使用await
。如果您像这样编写函数,那么您可以立即执行您的let result = 2 + 2;
行:
const timeout =
seconds => new Promise(res => setTimeout(res, seconds * 1000));
function myAPICall() {
// simulate 1 second wait time
return timeout(1).then(() => 'success');
}
async function myAsyncFunction() {
try {
console.log('starting');
// just starting the API call and storing the promise for now. not waiting yet
let dataP = myAPICall('https://jsonplaceholder.typicode.com/posts/1');
let result = 2 + 2;
// Executes right away
console.log('result', result);
// wait now
let data = await dataP;
// Executes after one second
console.log('data', data);
return data;
} catch (ex) {
return ex;
}
}
myAsyncFunction();
经过一些澄清后,我可以看到您真正想知道的是如何避免必须一个一个地等待两个异步操作,而是让它们并行执行。事实上,如果你一个await
接一个地使用,第二个在第一个完成之前不会开始执行:
const timeout =
seconds => new Promise(res => setTimeout(res, seconds * 1000));
function myAPICall() {
// simulate 1 second wait time
return timeout(1).then(() => 'success');
}
async function myAsyncFunction() {
try {
console.log('starting');
let data1 = await myAPICall('https://jsonplaceholder.typicode.com/posts/1');
// logs after one second
console.log('data1', data1);
let data2 = await myAPICall('https://jsonplaceholder.typicode.com/posts/2');
// logs after one more second
console.log('data2', data2);
} catch (ex) {
return ex;
}
}
myAsyncFunction();
为了避免这种情况,你可以做的是通过执行它们而不等待它们来启动两个异步操作,将它们的承诺分配给一些变量。然后你可以等待两个承诺:
const timeout =
seconds => new Promise(res => setTimeout(res, seconds * 1000));
function myAPICall() {
// simulate 1 second wait time
return timeout(1).then(() => 'success');
}
async function myAsyncFunction() {
try {
console.log('starting');
// both lines execute right away
let dataP1 = myAPICall('https://jsonplaceholder.typicode.com/posts/1');
let dataP2 = myAPICall('https://jsonplaceholder.typicode.com/posts/2');
let data1 = await dataP1;
let data2 = await dataP2;
// logs after one second
console.log('data1', data1);
console.log('data2', data2);
} catch (ex) {
return ex;
}
}
myAsyncFunction();
另一种方法是使用Promise.all()
一些数组分解:
const timeout =
seconds => new Promise(res => setTimeout(res, seconds * 1000));
function myAPICall() {
// simulate 1 second wait time
return timeout(1).then(() => 'success');
}
async function myAsyncFunction() {
try {
console.log('starting');
// both myAPICall invocations execute right away
const [data1, data2] = await Promise.all([
myAPICall('https://jsonplaceholder.typicode.com/posts/1'),
myAPICall('https://jsonplaceholder.typicode.com/posts/2'),
]);
// logs after one second
console.log('data1', data1);
console.log('data2', data2);
} catch (ex) {
return ex;
}
}
myAsyncFunction();