您還有第三種選擇,現在可以利用這個純粹出於輿論的境界:承諾+ async
/await
:
ES2017(出來六月規範)將採用async
/await
,提供更簡單用於在簡單用例中使用承諾的語法,並且NodeJS已經在當前版本的Node v7中支持它們(本文撰寫時爲v7.7.2)。
隨着承諾和async
/await
,你的代碼應該是這樣的:
const p = require(/*...some theoretical promisifier...*/).promisifier;
const fs = require('fs');
async function go() {
const myFile = '/home/tjc/temp/test';
let txt = await p(fs.readFile, myFile, 'utf8');
txt = txt + '\nAppended something!';
await p(fs.writeFile, myFile, txt);
console.log('Appended text!');
}
go().catch(error => {
console.log(error);
});
它仍然是異步的,它只是簡單的承諾使用情況的語法更加簡單,讓你有代碼反映邏輯沒有中介then
回調函數。
請注意,您只能在async
函數內使用await
(因爲它們在後臺管理承諾)。另外請注意,NodeJS很快就會對未處理的承諾拒絕產生不滿,因此請確保我們在go()
上執行catch
。
我相信上面的大致轉換爲以下幾點:
const p = require(/*...some theoretical promisifier...*/).promisifier;
const fs = require('fs');
function go() {
const myFile = '/home/tjc/temp/test';
return p(fs.readFile, myFile, 'utf8').then(txt => {
txt = txt + '\nAppended something!';
return p(fs.writeFile, myFile, txt).then(() => {
console.log('Appended text!');
});
});
}
go().catch(error => {
console.log(error);
});
...但當然,如果你自己寫吧,你會安排不同的看法:
const p = require(/*...some theoretical promisifier...*/).promisifier;
const fs = require('fs');
function go() {
const myFile = '/home/tjc/temp/test';
return p(fs.readFile, myFile, 'utf8')
.then(txt => {
txt = txt + '\nAppended something!';
return p(fs.writeFile, myFile, txt);
})
.then(() => {
console.log('Appended text!');
});
}
go().catch(error => {
console.log(error);
});
正如你可以看出,就清晰度而言,async
/await
對於簡單用例會帶來許多問題。 (對於更復雜的用例,您仍然需要回到明確的承諾處理。)
然而,是否將我們帶出意見領域還是另一個問題。自然而然,保持你的函數小和可組合是一件好事,不管你是否使用promise。
關於p
在上面:有各種不同的庫了那裏promisifying使用節點的標準回調機制寫入的API;在上面我使用的是理論上的。這裏是一個非常,非常,非常簡單的實現p
以上:
const p = (f, ...args) => {
return new Promise((resolve, reject) => {
args.push((err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
f(...args);
});
};
exports.promisifier = p;
...但你可以發現,採取更徹底的辦法庫。
「readFileSync」如何? – blackmiaool
@blackmiaool:不要在NodeJS中使用同步函數,而沒有真正的原因。 –