async函数

  • Generator 函数的语法糖 使异步操作更简略
  • async示意函数里有异步操作,await示意紧跟在前面的表达式须要期待后果。
  • 返回值 一个Promise对象,能够用then办法指定下一步操作

    • async函数return的值通过Promise对象resolved时候的data获取
    • async函数throw的谬误通过Promise对象rejected时候的error获取
async function test() {    return 1;}const p = test();console.log(p); // Promise {<resolved>: 1}__proto__: Promise[[PromiseStatus]]: "resolved"[[PromiseValue]]: 1p.then(function(data) {    console.log(data); // 1});
async function test() {    throw new Error("error");}const p = test();console.log(p);  // Promise {<rejected>: Error: error...}p.catch(function(err) {    console.log(err); // Error: error});

await

  • await命令只能用在async函数之中
  • await后能够是Promise对象和原始类型的值(数值、字符串和布尔值,但这时会主动转成立即resolved的Promise对象)
  • await后Promise对象状态变为rejected,后续执行中断

await后Promise对象状态为resolved

async function async1() {    console.log("async1 start");    let r = await async2();    console.log(r)    console.log("async1 end");}async function async2() {    return Promise.resolve().then(_ => {        console.log("async2 promise");        return "value from async2"    });}async1();
  1. 执行async1,打印"async1 start"
  2. 执行await async2(),await会期待Promise变成resolved状态,而后拿到返回值,因而会执行Promise.resolve().then(),打印"async2 promise"
  3. async2中then函数返回的值被赋值给r,打印"value from async2"
  4. 打印"async1 end"

await后Promise对象状态为reject

await Promise.reject("error")后的代码不会被执行

async function f() {    await Promise.reject("error");    console.log(1);    await 100;}f();

解决异样后,前面的代码就会执行了

  • 通过Promise 对象的catch办法

    async function f() {    await Promise.reject("error").catch(err => {        // 解决异样    });    console.log(1);    await 100;}f();
  • 通过try{}catch{}捕捉异样

    async function f() {    try {        await Promise.reject("error");    } catch {        // 解决异样    }    console.log(1);    await 100;}f();

实现原理

Generator + 主动执行器

// 应用async函数 返回Promise对象async function example(params) {    // ...}// 实现function example(params) {    return spawn(function*() {        // ...    });}function spawn(genF) {    return new Promise(function(resolve, reject) {        const gen = genF(); // 生成器对象        function step(nextF) {            let next;            try {                next = nextF(); // 执行gen.next            } 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);        });    });}

利用

按程序打印文件
Promise实现

function readFilesByPromise() {    const fs = require('fs')    const path = require('path')    const files = [        './file/a.json',        './file/b.json',        './file/c.json'    ]    function readFile(url) {        return new Promise((resolve, reject) => {            fs.readFile(path.join(__dirname, url), function (err, data) {                if (err) { reject(err) }                resolve(data)            })        })    }    readFile(files[0])        .then((data) => {            console.log(data.toString())            return readFile(files[1])        })        .then((data) => {            console.log(data.toString())            return readFile(files[2])        })        .then((data) => {            console.log(data.toString())        })}readFilesByPromise()

async/await实现

async function readFilesByAsync() {    const fs = require('fs')    const path = require('path')    const files = [        './file/a.json',        './file/b.json',        './file/c.json'    ]    function readFile(url) {        return new Promise((resolve, reject) => {            fs.readFile(path.join(__dirname, url), function (err, data) {                if (err) { reject(err) }                resolve(data)            })        })    }    const str1 = await readFile(files[0])    console.log(str1.toString())    const str2 = await readFile(files[1])    console.log(str2.toString())    const str3 = await readFile(files[2])    console.log(str3.toString())}readFilesByAsync()