复习ES6 - async await

要了解async,需要先了解Genertao函数是es6提供的一种异步编程解决。
它具备以下两个特征

  • function关键字与函数名之间有一个*号
  • 函数内部使用yield(产出)表达式,定义不同的内部状态,
function* helloWorldGenerator() {
  yield 'hello';
  yield 'world';
  return 'ending';
}
var hw = helloWorldGenerator();

调用和平时函数没什么区别,但是调用完函数并不执行,返回的也不是函数运行的结果,返回的是一个指向内部状态的指针对象(Iterator)

遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)

// 调用遍历器对象的next方法,使得指针移向下一个状态
hw.next()
// { value: 'hello', done: false }

hw.next()
// { value: 'world', done: false }

hw.next()
// { value: 'ending', done: true }

hw.next()
// { value: undefined, done: true }

遍历器对象的next方法的运行逻辑如下。

  • (1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
  • (2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
  • (3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。
  • (4)如果该函数没有return语句,则返回的对象的value属性值为undefined。

async
async 函数是什么?一句话,它就是 Generator 函数的语法糖。看个列子差不多大家就知道了

const fs = require('fs');
const readFile = function (fileName) {
  return new Promise(function (resolve, reject) {
    fs.readFile(fileName, function(error, data) {
      if (error) return reject(error);
      resolve(data);
    });
  });
};
const gen = function* () {
  const f1 = yield readFile('/etc/fstab'); // 注意yield
  const f2 = yield readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};
// 等价与上面
const asyncReadFile = async function () {
  const f1 = await readFile('/etc/fstab');
  const f2 = await readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};

async函数返回一个 Promise 对象。
async函数内部return语句返回的值,会成为then方法回调函数的参数。
async函数内部一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

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).then(() => console.log(1)); 
// hello world
// 1

记住await几个要点

  • await命令后面的 Promise 对象如果变为reject状态,则reject的参数会被catch方法的回调函数接收到。并且整个async函数都会中断执行。
async function f() {
  await Promise.reject('出错了');
 await Promise.resolve('hello world'); // 不会执行
}
f()
.then(v => console.log(v))
.catch(e => console.log(e))
// 出错了

有时,我们希望即使前一个异步操作失败,也不要中断后面的异步操作。这时可以将第一个await放在try...catch结构里面

async function f() {
  try {
    await Promise.reject('出错了');
  } catch(e) {
  }
  return await Promise.resolve('hello world');
}

f()
.then(v => console.log(v))

重点来了
async函数的实现原理

async 函数的实现原理,就是将 Generator 函数和自动执行器,包装在一个函数里。

async function fn(args) {
  // ...
}
// 等同于
// spawn函数是一个制动执行器
function fn(args) {
  return spawn(function* () {
    // ...
  });
}

你可能感兴趣的:(复习ES6 - async await)