簡體   English   中英

Javascript:promise 鏈 vs. async/await?

[英]Javascript : promise chain vs. async/await?

我正在學習 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);
}

在使用承諾鏈為 ChainReadJson 函數編寫代碼時,我很難控制執行結果和錯誤。 但是,當使用 async/await 編寫 AwaitReadJson 函數的代碼時,這些困難大多消失了。

我是否正確理解 async/await 的好處? 與承諾鏈相比,async/await 的缺點是什么?

(示例代碼是此答案中代碼的修改版本。原始代碼僅使用承諾鏈,並編寫以確切了解錯誤發生在鏈中的哪個位置以及錯誤是什么)

實際上,與回調、promise 和生成器函數相比, async/await旨在減少樣板代碼並使異步程序更易於編寫。

  • 雖然 promises 是為相同的目標創建的,但它們具有必須在現有 JS 引擎中工作的額外限制——因此它們的語法更加復雜。 使用 async/await 需要一個相對較新的 JS 引擎 如果您正在編寫自己的 node.js 應用程序可能無關緊要,但是庫可能需要與舊的 node.js 版本兼容(我不確定您是否可以在沒有發電機支持)。
  • 由於 async/await 較新,因此沒有優化 去年的一項比較報告稱, Bluebird promises(一個實現簡化版本 promise 的 JS 庫)在某個基准測試中的表現優於 async/await。 (當然,當您的用例發出一些網絡請求時,這可能無關緊要。)
  • 您可能仍然需要承諾並行執行多個異步操作(編輯:如果您需要它們的結果)

雖然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處理程序,這將導致重復記錄,如果你找不到過濾掉它的方法。

這是可行的,但有點痛苦,所以我把它從上面的代碼中去掉了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM