Javascript:promise chain vs. async / await?

时间:2018-05-07 22:21:56

标签: javascript node.js async-await es6-promise

我正在了解Javascript Promiseasync / await。下面的示例代码异步读取并解析node.js中的JSON文件(我的node.js版本是v10.0.0 )。

在示例代码中,ChainReadJson函数和AwaitReadJson函数正在做同样的事情,读取和解析JSON文件。区别在于ChainReadJson函数使用promise链,而AwaitReadJson函数使用async / await。

const FS = require("fs");

function ReadFile(fileName) {
    return new Promise((Resolve, Reject) => {
        FS.readFile(fileName, 'utf8', (error, result) => {
            if (error)
                Reject(error);
            else
                Resolve(result);
        });
    });
}

// function using promise chain

function ChainReadJson(fileName, CallBack) {
    ReadFile(fileName)
        .then(
            res => JSON.parse(res),
            err => {
                Message(-1, err.message);
            }
        )
        .then(
            res => {
                if (res !== undefined)
                    CallBack(fileName, res);
            },
            err => {
                Message(-2, err.message);
            }
        );
}

// function using async/await

async function AwaitReadJson(fileName, CallBack) {
    let res, json;

    try {
        res = await ReadFile(fileName);
    }
    catch (err) {
        Message(-1, err.message);
        return;
    }
    try {
        json = JSON.parse(res);
    }
    catch (err) {
        Message(-2, err.message);
        return;
    }
    CallBack(fileName, json);
}

ChainReadJson('test.json', PrintJSON);
AwaitReadJson('test.json', PrintJSON);

// common functions

function PrintJSON(fileName, json) {
    console.log(`JSON[${fileName}]:`, json);
}

function Message(n, str) {
    console.log(`[${n}]`, str);
}

使用promise chain编写ChainReadJson函数的代码时,我很难控制执行结果和错误 但是,当使用async / await编写AwaitReadJson函数的代码时,这些困难大多都消失了。

我是否正确理解async / await的好处?与promise链相比,async / await有哪些缺点?

(示例代码是the code in this answer的修改版本。原始代码仅使用promise链,并且编写以确切地知道错误发生在链中的哪个位置以及错误是什么)

2 个答案:

答案 0 :(得分:9)

实际上,与回调,承诺和生成器函数相比,.cent { align: center; position: absolute; top: 40%; left: 45%; } designed来减少样板并使异步程序更容易编写。

  • 虽然promises是以相同的目标创建的,但它们还有必须在现有JS引擎中工作的附加约束 - 因此它们的语法更复杂。 使用async / await需要relatively new JS engine如果您正在编写自己的node.js应用程序可能无关紧要,但是库可能需要与较旧的node.js兼容版本(我不确定你是否可以将其转换为在没有生成器支持的旧浏览器中使用)。
  • 由于async / await较新,并未优化。去年reports Bluebird承诺(一个实现简化版承诺的JS库)的表现优于某个基准测试中的async / await。 (当然,当您的用例发出一些网络请求时,这可能无关紧要。)
  • 您可能仍然need promises to execute several asynchronous actions in parallel(编辑:如果您需要他们的结果)

答案 1 :(得分:3)

尽管async/await可以是一种清理异步逻辑的好方法,但值得指出的是,可以清楚地清除promise逻辑,以至于非常类似于async / await替代:

const fs = require("fs");
const util = require("util")

//Could also use the experimental "fs/promise" api from node v10
const promisifiedReadFile = util.promisify(fs.readFile);

const readFile = (fileName) => promisifiedReadFile(fileName, 'utf8');

function chainReadJson(fileName, callback) {
    return readFile(fileName)
        .then(json => JSON.parse(json))
        .then(result => callback(null, result))
        .catch(e => {
            console.log("Error reading or parsing file", e.message);
            callback(e)
        });
}

这里唯一的功能区别是所有错误记录都发生在链的末尾的一个地方。

可以保留readFile和JSON.parse的拆分日志记录,但这无疑是有点棘手的。您通常希望在处理错误后重新抛出错误,以便跳过下游.then处理程序:但如果再次抛出错误,下游.catch处理程序将再次捕获该错误。如果您没有找到过滤它的方法,将导致重复记录。

这是可行的,但这有点痛苦,所以我把它从上面的代码中删除了。