Q promises – 数组中每个元素的Node.js函数

函数dirList()应该返回definded目录内的文件夹数组。 我不明白如何返回dirListvariables只有在函数isDir()执行每个文件。

我想我应该使用Q.all() ,但我不知道我应该把它放在:-(

 var fs = require('fs'), Q = require('q'), readdir = Q.denodeify(fs.readdir); function isDir(path) { return Q.nfcall(fs.stat, __dirname + path) .then(function (stats) { if (stats.isDirectory()) { return true; } else { return false; } }); } function dirList(path) { return readdir(__dirname + path).then(function (files) { var dirList = files.filter(function (file) { return isDir(path + file).then(function (isDir) { return isDir; }); }); return dirList; }); } dirList('/').done( function (data) { console.log(data); }, function (err) { console.log(err); } ); 

你遇到的问题是, Array.prototype.filter不知道承诺,所以它只看到一个真值(实际上是一个承诺对象),并将文件添加到输出列表。 解决这个问题的一种方法如下(AsyncJS可能有一种“干净”的方式):

 'use strict'; var fs = require('fs'), Q = require('q'), readdir = Q.denodeify(fs.readdir); function isDir(path) { return Q.nfcall(fs.stat, __dirname + path) .then(function (stats) { return stats.isDirectory(); }); } function dirList(path) { return readdir(__dirname + path).then(function (files) { // here we map the list of files to an array or promises for determining // if they are directories var dirPromises = files.map(function (file) { return isDir(path + file); }); // here is the Q.all you need return Q.all(dirPromises) // here we translate the array or directory true/false values back to file names .then(function(isDir) { return files.filter(function(file, index) { return isDir[index]; }); }); }); } dirList('/').done( function (data) { console.log(data); }, function (err) { console.log(err); }); 

数组filter方法不能使用asynchronouspromise结果,它期望一个布尔值被同步返回。

我会build议使用一个函数来检查一个给定的path是否是一个目录,如果是这样的话就返回一个文件的承诺,否则就没有任何承诺。 然后,您可以用Q.all()等待每个path的结果,然后一起join“积极”结果,省略“否定”结果:

 function isDir(path) { return Q.nfcall(fs.stat, __dirname + path).invoke("isDirectory"); } function dirList(path) { return readdir(__dirname + path).then(function (files) { var maybeDirPromiseList = files.map(function (file) { return isDir(path + file).then(function (isDir) { return isDir ? [file] : []; // Maybe represented as list }); }); var maybeDirsPromise = Q.all(maybeDirPromiseList); return maybeDirsPromise.then(function(maybeDirList) { return [].concat.apply([], maybeDirList); // is equivalent to: var dirList = []; for (var i=0; i<maybeDirList.length; i++) if (maybeDirList[i] && maybeDirList[i].length > 0) dirList.push(maybeDirList[i][0]); return dirList; }); }); }