如何等待异步函数?

时间:2017-01-17 12:32:14

标签: javascript asynchronous ecmascript-2017

我的情况:



let waiting = function () {
  return new Promise(resolve => {
    console.log('awaiting...');
    
    setTimeout(function () {
      resolve();
    }, 1000)
  });
};

let waitingAsync = async function () {
  console.log('start...');

  await waiting();

  console.log('stop...');
};

waitingAsync();
console.log('done...');




我不会在代码中理解两件事:

第一个:

await waiting();

waiting是一个同步函数(因为它没有async个关键字)。那么,为什么我可以等待同步函数呢?

第二个:

为什么在完成done...功能后无法等待waitingAsync消息?

主要问题:waitingAsync是一个异步函数,调用它时为什么不需要await关键字?只需waitingAsync()而不是await waitingAsync()

如果我可以等待waitingAsync(),最后会打印done...条消息。

4 个答案:

答案 0 :(得分:4)

这不是一个函数,而是一个返回的值,等待await语句。

async和普通函数与调用者没有区别。 async只返回一个promise而不会在被调用时显式返回它。 waitingAsync()电话的结果是一个承诺。 waiting()调用的结果也是一个承诺,因此它不是'同步'。

根据the spec,承诺和非承诺都可以await。非承诺将转换为Promise.resolve()的承诺。

无法等待

console.log('done...'),因为它未在async函数内调用。并且它不必是await,因为它不会返回承诺,而是undefined。在await函数中可以async。这些await用法是平等的,同样没用,他们所做的只是1个滴答延迟:

async function ... {
  ...
  await console.log('done...');
}

async function ... {
  ...
  console.log('done...');
  await undefined;
}

async function ... {
  ...
  await Promise.resolve(console.log('done...'));
}

答案 1 :(得分:2)

async函数确实返回一个promise,或者当它使用await关键字时,它必须等待一个异步函数,即Promise或另一个async函数。在您的代码中,waiting()是一个返回Promise的函数。然后,await waiting()是正确的(因为它正在等待异步函数)。

调用async函数,因为调用了另一个基本函数。当您希望将某个函数作为异步函数运行并使用“等待”时,可以将函数标记为异步。关键词。完成了......'是打印的,因为当您致电asyncFunction()时,它必须await,直到waiting promise完成。但程序没有停止,继续显示done...。如果您想等待它,也许您可​​以使用asyncFunction().then( () => console.log('done...') )

答案 2 :(得分:2)

当你await一个函数时,如果该函数返回一个promise,它的返回值将被视为promise then值。如果承诺拒绝,它将被转换为错误。如果函数调用返回的东西比那个函数更好,那么,await就没有了。

另一方面,当你声明一个async函数时,它的返回值将作为Promise返回,并且从它抛出的任何Error都将被转换为被拒绝的Promise。

您只能在await声明的函数中使用async

只是asyncawait,只是自动转换为承诺。你实际上并不需要使用await和async的代码实际上是异步的(虽然,它确实没用)。

快速演示:

//Will return the string 'Promise' if called through `await`
function getPromise(){
    return Promise.resolve('Promise');
}

//Casted to Promise.reject thrught await 
function throwError(){
    return Promise.reject('error'); 
}

function get(){
    return 'something simple'; 
}

async function getAsync() {
    var response = await getPromise();
    return response;
}
//await will cast the rejected Promise to an error
async function getErrorAsync() {
    var response = await throwError();
    return response;
}

async function simpleGet(){
    return get();
}

async function redundantGet(){
    return await get();
}

    async function catchTheError(){
      try{
          await throwError();
      }       
      catch(e){
         console.log('an error: ' + e );
      }
       return 'whatever';
 }

getAsync().then( console.log ); //Promise
getErrorAsync().catch( console.log ); //error
simpleGet().then( console.log ); //something simple
redundantGet().then( console.log ); //something simple
catchTheError(); //will log 'an error: error'.

所以:

  

waiting是一个同步函数(因为它没有async关键字)。那么,为什么我可以等待同步函数呢?

因为你可以。 await唯一能做的就是解决对真实值和错误的承诺。您实际上并不需要该函数来返回承诺。

  

为什么不能完成...在完成waitingAsync功能后等待消息?

asyncawait只会使您的代码与同步iside async声明的函数一样运行。您的上一个console.log('done')在任何async函数之外,因此它将在该函数结束之前被记录,因为它是异步的。

  

主要问题:waitingAsync是一个异步函数,为什么调用它时不需要await关键字?只需waitAsync()而不是等待waitingAsync()。

因为async关键字将值转换为承诺 - 并且允许使用await - 仅此而已。事实上,由于你只能在await函数中使用async ...你不能指望通过async调用await函数,你需要无限async 1}}函数:-D。

答案 3 :(得分:1)

Async关键字用于指定该函数将是AsyncFunction的实例,因此它将返回Promise

Await用于等待在异步函数内解析的承诺。

According to a mdn - 异步函数可以包含一个await表达式,它暂停执行异步函数并等待传递的promise的解析,然后恢复异步函数的执行并返回已解析的值。