【发布时间】:2013-09-05 15:40:19
【问题描述】:
我认为这是一个非常愚蠢的问题,但我很难理解承诺。
我正在使用 Q(用于 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 函数回调链中的最后一个函数。这个函数基本上和函数'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传递任何回调?此外,如果您的问题是关于该功能的,您应该认真地将其代码包含在您的问题中...... -
只需使用
var first = Q.nfbind(fs.readdir, path);:-) -
您能详细说明一下吗?此外,我已按要求添加了整个功能。感谢您的宝贵时间!
标签: javascript node.js promise deferred q