2015-12-03 123 views
1

我试图使用q承诺库在目录中获取.json文件的名称并返回这些文件的内容。我能够获取文件名,但我无法使用arr.map与promise,以便读取文件的内容。我希望getContents()能够返回一个带有指定文件名内容的映射数组。在地图上使用q承诺获取文件内容

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()的承诺,使我的数组中的内容不等于不确定?

回答

1

首先,您需要获得一组承诺 - 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'); 
    })); 
} 
+0

是否有使用'JSON.parse()来'对结果的简单方法'Q.nfcall()'? – Himmel

+1

只要执行'Q.nfcall(...).then(JSON.parse)'(就像每个其他承诺为JSON文本一样) – Bergi

0

首先,你可以定义使用承诺的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'); 
    }); 
}