大家好我很难理解异步和等待在幕后工作的方式。我知道我们有通过使用“then”函数制作非阻塞代码的promise,我们可以在promise解决后放置我们需要做的所有工作。我们希望做的工作与我们希望并行,我们只需将它写在我们的函数之外。因此代码变得非阻塞。但是,我不明白async
await
如何制作非阻止代码。
async function myAsyncFunction() {
try {
let data = await myAPICall('https://jsonplaceholder.typicode.com/posts/1');
// It will not run this line until it resolves await.
let result = 2 + 2;
return data;
}catch (ex){
return ex;
}
}
参见上面的代码。在API调用解决之前,我无法继续前进。如果它使我的代码阻止代码,那么它比promises更好吗?或者我错过了关于async
和await
的内容吗?我在哪里放置不依赖于等待调用的代码?所以它可以继续工作而不等待执行?
我正在添加一个Promise代码,我希望在async await示例中进行复制。
function myPromiseAPI() {
myAPICall('https://jsonplaceholder.typicode.com/posts/1')
.then(function (data) {
// data
});
// runs parallel
let result = 2 + 2;
}
答案 0 :(得分:25)
正如其名称所暗示的那样,await
关键字将导致该功能等待"等待"直到它的承诺在执行下一行之前解决。
这个和阻塞代码之间的区别在于,当函数等待异步操作完成时,函数将继续执行 outside 函数。
async
和await
只是承诺之上的语法糖。它们允许您编写看起来很像普通同步代码的代码,即使它使用了承诺。如果我们将您的示例转换为明确使用promises的内容,它将类似于:
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;
行:
function myAPICall() {
// simulate 1 second wait time
return new Promise(resolve => setTimeout(resolve, 1000))
.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);
let data = await dataP;
// Executes after one second
console.log(data);
return data;
} catch (ex) {
return ex;
}
}
myAsyncFunction();

经过一些澄清后,我可以看到你真正想知道的是如何避免必须逐个等待两个异步操作,而是让它们并行执行。实际上,如果你在另一个之后使用一个await
,那么第二个不会开始执行,直到第一个完成:
function myAPICall() {
// simulate 1 second wait time
return new Promise(resolve => setTimeout(resolve, 1000))
.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);
let data2 = await myAPICall('https://jsonplaceholder.typicode.com/posts/2');
// logs after one more second
console.log(data1);
} catch (ex) {
return ex;
}
}
myAsyncFunction();

为了避免这种情况,你可以做的是启动两个异步操作,通过执行它们而不等待它们,将它们的promises分配给某些变量。然后你可以等待两个承诺:
function myAPICall() {
// simulate 1 second wait time
return new Promise(resolve => setTimeout(resolve, 1000))
.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);
console.log(data2);
} catch (ex) {
return ex;
}
}
myAsyncFunction();

另一种方法是使用Promise.all()
进行一些数组分解:
function myAPICall() {
// simulate 1 second wait time
console.log('myAPICall called');
return new Promise(resolve => setTimeout(resolve, 1000))
.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);
console.log(data2);
} catch (ex) {
return ex;
}
}
myAsyncFunction();