我认为这是一个非常愚蠢的问题,但我很难将我的头包裹在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