使用q promises with map来获取文件内容

时间:2015-12-03 00:48:55

标签: javascript node.js promise q

我正在尝试使用q promise库来获取目录中.json个文件的名称,并返回这些文件的内容。我能够获取文件名,但是我在将arr.map与promises结合使用时无法读取文件的内容。我希望getContents()返回带有指定文件名内容的映射数组。

function readDir() {
    var deferred = q.defer();
    fs.readdir('users', function(err, data) {
        if (err) console.log(err);
        deferred.resolve(data);
    })
    return deferred.promise;
}

function getContents(filenames) {
    return filenames.map(function(filename) {
        fs.readFile('users/' + filename, 'utf8', function(err, result) {
            return result;
        });
    });
}

readDir()
    .then(getContents)
    .then(function(fileContents) {
        // currently returns undefined
        console.log(fileContents);
    });

如何正确地将getConents()包装在一个promise中,以便我的数组内容不等于undefined?

2 个答案:

答案 0 :(得分:1)

首先,您需要获取一组promise - return result在异步回调中无用。为每一个readFile电话做出承诺:

filenames.map(function(filename) {
    return Q.nfcall(fs.readFile, 'users/' + filename, 'utf8');
//  ^^^^^^ here's where the return is needed
})

Q.nfcall function基本上与您在readDir函数中写出的内容相同。

现在您已经获得了一系列承诺,您可以使用Q.all轻松将其转换为数组的承诺(等待所有承诺):

function getContents(filenames) {
    return Q.all(filenames.map(function(filename) {
        return Q.nfcall(fs.readFile, 'users/' + filename, 'utf8');
    }));
}

答案 1 :(得分:0)

首先,您可以使用promises:

定义fs.readFile的正确异步版本
function readFileAsync(/* ...args */) {
    return Q.nfapply(fs.readFile, arguments);
}

之后,您有两种选择。这将并行读取文件:

function getContents(filenames) {
    return Q.all(
        filenames.map(function(filename) {
            return readFileAsync('users/' + filename, 'utf8');
        })
    );
}

这将逐一阅读:

function qMap(array, selector) {
    var i = 0;
    var result = [];


    function store(x) {
        result.push(x);
        return next();
    }

    function next() {
        if (i < array.length) {
            var index = i++;
            var item = array[index];
            return Q.fcall(selector, item, index).then(store);
        } else {
            return result;
        }
    }

    return Q.fcall(next);
}

function getContents(filenames) {
    return qMap(filenames, function(filename) {
        return readFileAsync('users/' + filename, 'utf-8');
    });
}