我認爲這是一個非常愚蠢的問題,但我很難將我的頭包裹在promise中。Q Promise鏈和NodeJS回調
我正在使用Q(for nodejs)來同步一些異步函數。 這工作就像一個魅力。
var first = function() {
var d = Q.defer();
fs.readdir(path,function(err,files){
if(err) console.log(err);
d.resolve(files);
});
return d.promise;
};
var second = function (files) {
var list = new Array;
files.forEach(function(value, index){
var d = Q.defer();
console.log('looking for item in db', value);
db.query(
'SELECT * FROM test WHERE local_name =? ', [value],{
local_name : String,
},
function(rows) {
if (typeof rows !== 'undefined' && rows.length > 0){
console.log('found item!', rows[0].local_name);
d.resolve(rows[0]);
} else {
var itemRequest = value;
getItemData(itemRequest);
}
}
);
list.push(d.promise);
});
return Q.all(list);
};
first()
.then(second)
.done(function(list){
res.send(list);
});
我的問題是這個小功能:
getItemData(itemRequest)
此功能充滿了幾個回調。承諾鏈運行的功能很好,但忽略了我使用的所有回調(例如,我在函數中進行的幾個XHR調用)。
功能的簡化版本看起來像這樣(只給你一個想法):
function getItemData(itemRequest){
helper.xhrCall("call", function(response) {
var requestResponse = JSON.parse(response)
, requestInitialDetails = requestResponse.results[0];
downloadCache(requestInitialDetails,function(image) {
image = localImageDir+requestInitialDetails.image;
helper.xhrCall("call2", function(response) {
writeData(item,image,type, function(){
loadData(item);
});
});
} else {
writeData(item,image,type, function(){
loadData(item);
});
}
});
});
我使用XHR功能如下:
xhrCall: function (url,callback) {
var request = require("request")
, colors = require('colors');
request({
url: url,
headers: {"Accept": "application/json"},
method: "GET"
}, function (error, response, body) {
if(!error){
callback(body);
}else{
console.log('Helper: XHR Error',error .red);
}
});
}
所以我的問題:
- 我可以保留函數不變,並使用回調函數是否到位?承諾鏈?
- 或者我必須重寫函數來使用XHR的promise嗎?
- 如果是這樣,我怎樣才能最好地寫我的承諾鏈?我應該拒絕forEach的最初承諾嗎?
再次,抱歉,如果這是一個非常愚蠢的問題,但我不知道什麼是正確的行動方式在這裏。
謝謝!
[編輯] Q.nfcall,我不明白這一點
所以我一直在尋找到Q.nfcall允許我使用節點回調。我只是不明白這是如何工作的。 有人可以給我一個簡單的例子,我將如何去使用它與幾個異步xhr調用函數?
我試過,但你可以看到我真的不明白我在做什麼:
var second = Q.nfcall(second);
function second (files) {
[編輯2]
這是我getitemdata功能最終funcction回調鏈。這個函數基本上和函數'second'一樣,但是我直接推送結果然後返回promise。這是按照說明的方式工作的,但沒有所有額外的回調數據,因爲它不會等待回調與任何數據一起返回。
function loadData(item) {
var d = Q.defer();
db.query(
'SELECT * FROM test WHERE local_name =? ', [item],{
local_name : String,
},
function(rows) {
if (typeof rows !== 'undefined' && rows.length > 0){
list.push(d.promise);
}
}
);
});
return Q.all(list);
};
你似乎沒有將任何回調傳遞給'getItemData'?此外,如果你的問題是關於這個功能,你應該認真的在你的問題中包括它的代碼... – Bergi
只需使用'var first = Q.nfbind(fs.readdir,path);':-) – Bergi
請你詳細說明一下嗎?另外,我已經按要求添加了整個功能。感謝您的時間! – jansmolders86