Javascript Promise
およびasync
/await
について学習しています。以下のサンプルコードは、node.js内のJSONファイルを非同期で読み取り、解析します(my node.js version is 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
was designed は、定型文を減らし、非同期プログラムを、コールバック、プロミス、ジェネレーター関数に比べて簡単に作成できるようにします。
async/await
は非同期ロジックをクリーンアップするための優れた方法です。promiseロジックを大幅にクリーンアップして、非同期/待機の代替手段に非常に類似していることを指摘しておくことは価値があります。
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)
});
}
ここでの唯一の機能的な違いは、すべてのエラーログがチェーンの最後の1か所で発生することです。
ReadFileとJSON.parseのスプリットロギングを保持することは可能ですが、それは確かに少しトリッキーです。エラーを処理した後、通常、エラーを再スローして、ダウンストリーム.then
ハンドラーはスキップされます。ただし、エラーを再度スローすると、ダウンストリームによって再度キャッチされます.catch
ハンドラ。これを除外する方法が見つからない場合、重複ロギングが発生します。
実行可能ですが、少し面倒なので、上のコードでは省略しました。