[英]How to persist data through promise chain in NodeJS (Bluebird)
將Bluebird / NodeJS Promises的參數交換為“ then”的后續操作(發布的答案有效,但立即發現了一個新問題)
這是我第一次在NodeJS中使用Promise,因此對於某些約定未得到嚴格遵守或代碼草率的行為,我深表歉意。 我正在嘗試聚合來自多個API的數據,將其放入數據庫中,然后根據數據的異同來計算一些統計信息。 首先,我嘗試獲取單個API的API令牌。
這是我的完整代碼:
var Promise = require('bluebird');
var fs = require('fs');
var request = require('request');
Promise.promisifyAll(fs);
Promise.promisifyAll(request);
// tilde-expansion doesn't follow the callback(err, data) convention
var tilde = function(str) {
var _tilde = require('tilde-expansion');
return new Promise(function(resolve, reject) {
try {
_tilde(str, resolve);
} catch(e) {
reject(e);
}
});
}
var getToken = function() {
return request.getAsync(process.env.token_url, {
headers: {
"Content-Type": "applications/x-www-form-urlencoded"
},
form: {
client_id: process.env.client_id,
client_secret: process.env.client_secret,
grant_type: "client_credentials"
}
})
.then(function(resp) { return resp.body; });
}
var tokenFile = tilde(process.env.token_file)
.catch(function(err) {
console.log("Error parsing path to file... can not recover");
});
var token = tokenFile
.then(fs.readFileAsync) //, "utf8")
.then(function(data) {
console.log("Token (from file): " + data);
return data;
})
.then(JSON.parse)
.catch(function(err) {
console.log("Error reading token from file... getting a new one");
return getToken()
.then(function(data) {
console.log("Token (from API): " + data);
return data;
})
.then(JSON.stringify)
.then(fs.writeFileAsync.bind(null, tokenFile.value()));
});
token.then(function(data) {
console.log("Token (from anywhere): " + token.value);
});
該代碼當前正在記錄:
Token: undefined
如果我退回到API。 假設我正確完成了我的諾言內容( .catch()
可以返回一個諾言,對嗎?),那么我會認為問題正在發生,因為fs.writeFileAsync
返回void。
我想追加一個.return()
這一承諾的結束,但我將如何獲得對返回值的訪問getToken()
我嘗試了以下方法:
.catch(function(err) {
console.log("Error reading token from file... getting a new one");
var token = "nope";
return getToken()
.then(function(data) {
console.log("Token (from API): " + data);
token = data;
return data;
})
.then(JSON.stringify)
.then(fs.writeFileAsync.bind(null, tokenFile.value()))
.return(token);
});
但是,這記錄為“不”。
在周末,我繼續了對諾言的研究,並且在實現關鍵性實現后,我得以開發出解決方案。 在此同時發布實現和解決方案:
發明了承諾,以便可以以同步方式使用異步代碼。 考慮以下:
var data = processData(JSON.parse(readFile(getFileName())));
這等效於:
var filename = getFileName();
var fileData = readFile(filename);
var parsedData = JSON.parse(fileData);
var data = processData(parsedData);
如果這些函數中的任何一個是異步的,那么它將中斷,因為該值未按時准備好。 因此,對於那些異步位,我們曾經使用回調:
var filename = getFileName();
var data = null;
readFile(filename, function(fileData){
data = processData(JSON.parse(fileData));
});
這不僅丑陋,而且破壞了很多東西,例如堆棧跟蹤,try / catch塊等。
Promise模式解決了這個問題,讓您說:
var filename = getFileName();
var fileData = filename.then(readFile);
var parsedData = fileData.then(JSON.parse);
var data = parsedData.then(processData);
不管這些函數是同步的還是異步的,此代碼都有效,並且回調為零。 它實際上是所有同步代碼,但是我們傳遞承諾而不是傳遞值 。
使我意識到: 對於可以用promise編寫的每一段代碼,都有一個同步的推論。
意識到這一點,我嘗試考慮所有功能是否都是同步的代碼:
try {
var tokenFile = tilde(process.env.token_file)
} catch(err) {
throw new Error("Error parsing path to file... can not recover");
}
var token = null;
try {
token = JSON.parse(readFile(tokenFile));
} catch(err) {
token = getToken();
writeFile(tokenFile, JSON.stringify(token));
}
console.log("Token: " + token.value);
在像這樣進行構架之后,promise版本在邏輯上如下:
var tokenFile = tilde(process.env.token_file)
.catch(function(err) {
throw new Error("Error parsing path to file... can not recover");
});
var token = tokenFile
.then(readFile)
.then(JSON.parse)
.catch(function(err) {
var _token = getToken();
_token
.then(JSON.stringify)
.then(writeFile.bind(null, tokenFile.value));
return _token;
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.