关于javascript:笔记JS异步编程asyncawait

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]]: 1

p.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()

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理