Zijue/blog

3.async+await处理异步任务

Opened this issue · 0 comments

Zijue commented

async+await的使用

这次我们使用async+await的方式编写串联读文件内容的逻辑,代码如下:

let fs = require('fs').promises;

async function read() {
    try {
        const a = await fs.readFile('a.txt', 'utf8');
        const b = await fs.readFile(a, 'utf8');
        return b;
    } catch (e) { // 此处catch错误后,不继续抛出错误就走成功态
        console.log(e);
    }
}

read().then(data => {
    console.log('success', data); // success 紫珏
}, err => {
    console.log(err);
})

可以发现,async+await本质上还是一个promise,同时还可以在函数体内try...catch。这是怎么实现的呢?

我们依旧用babel编译看看:

"use strict";

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
    try {
        var info = gen[key](arg);
        var value = info.value;
    } catch (error) {
        reject(error);
        return;
    }
    if (info.done) {
        resolve(value);
    } else {
        Promise.resolve(value).then(_next, _throw);
    }
}

function _asyncToGenerator(fn) {
    return function () {
        var self = this, args = arguments;
        return new Promise(function (resolve, reject) {
            var gen = fn.apply(self, args);
            function _next(value) {
                asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
            }
            function _throw(err) {
                asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
            }
            _next(undefined);
        });
    };
}

var fs = require('fs').promises;

function read() {
    return _read.apply(this, arguments);
}

function _read() {
    _read = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
        var a, b;
        return regeneratorRuntime.wrap(function _callee$(_context) {
            while (1) {
                switch (_context.prev = _context.next) {
                    case 0:
                        _context.prev = 0;
                        _context.next = 3;
                        return fs.readFile('a.txt', 'utf8');

                    case 3:
                        a = _context.sent;
                        _context.next = 6;
                        return fs.readFile(a, 'utf8');

                    case 6:
                        b = _context.sent;
                        return _context.abrupt("return", b);

                    case 10:
                        _context.prev = 10;
                        _context.t0 = _context["catch"](0);
                        console.log(_context.t0);

                    case 13:
                    case "end":
                        return _context.stop();
                }
            }
        }, _callee, null, [[0, 10]]);
    }));
    return _read.apply(this, arguments);
}

通过观察代码不难发现,async+await编译出来的结果就是在generator的基础上又包裹了一层函数_asyncToGenerator,而此函数跟co库的核心原理基本一致:

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
    try {
        var info = gen[key](arg); // var info = it.next(value)
        var value = info.value; // info.value => yield的返回值
    } catch (error) {
        reject(error);
        return;
    }
    if (info.done) {
        resolve(value);
    } else {
        Promise.resolve(value).then(_next, _throw); // 报错就会执行_throw函数
        /**
        try {
            var info = gen[key](arg); // it.throw(err),这样async中可以try...catch
            var value = info.value;
        } catch (error) {
            reject(error);
            return;
        }
         */
    }
}

function _asyncToGenerator(fn) {
    return function () {
        var self = this, args = arguments;
        return new Promise(function (resolve, reject) {
            var gen = fn.apply(self, args);
            function _next(value) {
                asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
            }
            function _throw(err) {
                asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
            }
            _next(undefined);
        });
    };
}

小结:async+await => co + generatorasync+await就是语法糖,本质上就是co库和generator,写起来像同步方法,但是内部还是递归调用异步方法。