es6解讀 - async函式

weixin_33978044發表於2018-02-07
  • async函式返回promise物件
      function timeout(ms) {
          return new Promise((resolve) => {
              setTimeout(resolve, ms);
          });
       }

      async function asyncPrint(value, ms) {
          await timeout(ms);
          console.log(value);
      }

      asyncPrint('hello world', 50);
    由於async函式返回的是 Promise 物件,可以作為await命令的引數。所以,上面的例子也可以寫成
下面的形式:
     async function timeout(ms) {
          await new Promise((resolve) => {
              setTimeout(resolve, ms);
          });
      }

      async function asyncPrint(value, ms) {
          await timeout(ms);
          console.log(value);
      }

    asyncPrint('hello world', 50);

async 函式的實現原理

async 函式的實現原理,就是將 Generator 函式和自動執行器,包裝在一個函式裡。
async function fn(args) {
  // ...
}

// 等同於

function fn(args) {
  return spawn(function* () {
    // ...
  });
}

所有的async函式都可以寫成上面的第二種形式,其中的spawn函式就是自動執行器。

下面給出spawn函式的實現,基本就是前文自動執行器的翻版。

function spawn(genF) {
  return new Promise(function(resolve, reject) {
    const gen = genF();
    function step(nextF) {
      let next;
      try {
        next = nextF();
      } catch(e) {
        return reject(e);
      }
      if(next.done) {
        return resolve(next.value);
      }
      Promise.resolve(next.value).then(function(v) {
        step(function() { return gen.next(v); });
      }, function(e) {
        step(function() { return gen.throw(e); });
      });
    }
    step(function() { return gen.next(undefined); });
  });
}

非同步遍歷

const asyncIterable = createAsyncIterable(['a', 'b']);
const asyncIterator = asyncIterable[Symbol.asyncIterator]();

asyncIterator
.next()
.then(iterResult1 => {
  console.log(iterResult1); // { value: 'a', done: false }
  return asyncIterator.next();
})
.then(iterResult2 => {
  console.log(iterResult2); // { value: 'b', done: false }
  return asyncIterator.next();
})
.then(iterResult3 => {
  console.log(iterResult3); // { value: undefined, done: true }
});

async promise await執行順序

  • Promise優先於setTimeout巨集任務。所以,setTimeout回撥會在最後執行。
  • Promise一旦被定義,就會立即執行。
  • Promise的reject和resolve是非同步執行的回撥。所以,resolve()會被放到回撥佇列中,在主函式執行完和setTimeout前呼叫。
  • await執行完後,會讓出執行緒。async標記的函式會返回一個Promise物件
async function async1(){
  console.log('async1 start')
  await async2()
  console.log('async1 end')
}
async function async2(){
  console.log('async2')
}
console.log('script start')
setTimeout(function(){
  console.log('setTimeout') 
},0)  
async1();
new Promise(function(resolve){
  console.log('promise1')
  resolve();
}).then(function(){
  console.log('promise2')
})
console.log('script end')

上述,在Chrome 66和node v10中,正確輸出是:

script start
async1 start
async2
promise1
script end
promise2
async1 end
setTimeout

相關文章