【发布时间】:2015-07-13 11:28:35
【问题描述】:
我正在尝试编写一个函数,该函数与以下使用带有承诺模式的回调模式编写的函数相同:
function readdirRecursive(path,handler,callback) {
var errs = [],
tree = {};
fs.readdir(path,function(err,dir) {
if(err)return callback(err);
var pending = dir.length;
if(!pending)return callback(null,tree);
dir.forEach(function(file) {
var newPath = Path.join(path,file);
fs.stat(newPath,function(err,stats) {
if(stats.isDirectory()) {
readdirRecursive(newPath,handler,function(err,subtree) {
tree[file] = subtree
handler(tree,newPath,file,"directory",function(err) {
if(err)errs.push(err);
if(!--pending)return callback(errs.length>0?errs:null,tree);
});
});
} else {
tree[file] = null;
handler(tree,newPath,file,"file",function(err) {
if(err)errs.push(err);
if(!--pending)return callback(errs.length>0?errs:null,tree);
});
}
});
});
});
};
这是我目前的尝试:
function readdirRecursive(path) {
var tree = {};
return Q.Promise(function(resolve,reject,notify) {
return readdir(path)
.then(function(dir) {
var futures = [];
var pending = dir.length;
if(!pending)return resolve(tree);
dir.forEach(function(file) {
var deferred = Q.defer();
var subPath = Path.join(path,file);
futures.push(stat(subPath)
.then(function(stats) {
if(stats.isDirectory()) {
tree[file] = tree;
var sub = readdirRecursive(subPath)
sub
.then(function(subtree) {
notify({
path:subPath,
name:file,
type:"directory",
done:deferred,
pending:pending
});
//return subtree;
},reject,notify);
} else {
tree[file] = null;
notify({
tree:tree,
path:subPath,
name:file,
type:"file",
done:deferred,
pending:pending
});
//return null;
}
//console.log("tree",tree);
deferred.promise()
.then(function() {
console.log("pending promise");
if(!--pending)resolve(tree);
}
,function(err) {
reject();
});
}));
});
return Q.all(futures)
.then(function(futures) {
console.log("hi",futures);
});
});
});
};
此代码将遍历整个树,但不会返回树,并且会发生通知操作,但延迟的承诺永远不会解决。
当延迟承诺在通知事件之前启动时,什么都不会发生。
我知道我可以通过将 done 函数交给进度事件而不是尝试给出某种承诺来解决这个问题,但我想在这里尽可能充分地使用承诺,例如,这个代码完全符合我的要求:
function readdirRecursive(path) {
var tree = {};
return Q.Promise(function(resolve,reject,notify) {
return readdir(path)
.then(function(dir) {
var futures = [];
var pending = dir.length;
if(!pending)return resolve(tree);
dir.forEach(function(file) {
var deferred = Q.defer();
var subPath = Path.join(path,file);
console.log("file",file);
/*deferred.promise()
.then(function() {
console.log("pending promise");
if(!--pending)resolve(tree);
}
,function(err) {
reject();
});*/
futures.push(stat(subPath)
.then(function(stats) {
if(stats.isDirectory()) {
var sub = readdirRecursive(subPath)
sub
.then(function(subtree) {
tree[file] = subtree
notify({
path:subPath,
name:file,
type:"directory",
done:function(err) {
console.log("pending promise");
if(err)return reject(err);
if(!--pending)resolve(tree);
},
pending:pending
});
//return subtree;
},reject,notify);
} else {
tree[file] = null;
notify({
tree:tree,
path:subPath,
name:file,
type:"file",
done:function(err) {
console.log("pending promise");
if(err)return reject();
if(!--pending)resolve(tree);
},
pending:pending
});
//return null;
}
//console.log("tree",tree);
}));
});
return Q.all(futures)
.then(function(futures) {
console.log("hi",futures);
});
});
});
};
这是将执行这些功能的代码:
readdirRecursive("../").then(function(tree) {
console.log("TREE!!!",tree);
},function(err) {
console.log("ERROR",err);
},function(progress) {
console.log("PRGRESS WAS MADE",progress);
progress.done();
});
【问题讨论】:
-
在 bluebird wiki 中有一个例子。
-
我正在阅读目录,如果我想将它们读入树中,我可以这样做,但我想将它们读入树中,然后使用通知进行一些额外的处理事件,关于他们每个人。找到你的例子:link 我也必须使用 Q,因此是标签。
-
progress 已弃用
-
那么最好以不同的方式处理它,尽管我对 node/js 相当熟练,但我对使用 Promise 完全陌生。我已经用“最终目标”的一些工作示例更新了代码,删除了一个承诺,但是考虑到这一点,我现在真的不知道该怎么做,因为通知操作是我在这里追求的功能类型.
-
作为 Stack Overflow 中最响亮的承诺倡导者之一 - 我不会在这里使用它们 - 你想流式传输多个结果而不是单个 - 如果你想流式传输它们,我会使用 Observable如果你想使用 Promise,或者将它们推入一个数组,然后
.all数组。
标签: javascript node.js promise q