节点中嵌套readFiles的承诺模式

时间:2018-08-13 14:10:15

标签: node.js promise

我是Node和Promise的新手,我感到困惑。

我正在读取一个json,其中包含有关我需要读取的其他json文件的信息。看起来像这样:

{ 
    id: 1,
    name: "My name",
    includes: [
        "#include1.json",
        "#include2.json",
        "#include3.json"
    ]
}

包含文件如下所示:

{
    id: 1,
    name: "Include 1",
    details: "I am include 1"
}

我需要做的是阅读主json,然后使用给定的所有include构造一个完整的json文档,因此它将如下所示:

{ 
    id: 1,
    name: "My name",
    includes: [
        {
            id: 1,
            name: "Include 1",
            details: "I am include 1"
        },
        {
            id: 2,
            name: "Include 2",
            details: "I am include 2"
        },
        {
            id: 3,
            name: "Include 3",
            details: "I am include 3"
        },
    ]
}

主json文件将指示要包含的内容。

我将readFile方法放入一个返回诺言的函数中

function readFile(filename, enc, err){
  return new Promise(function (fulfill, reject){
    if(err) reject(err);
     fs.readFile(filename, enc, function (err, res){
      if (err) reject(err);
      else fulfill(res);
    });
  });
}

而我的服务文件占用了

serviceReturnJsonPromise = function() {
 return readFile(masterPath, 'utf8', err).then(function (masterData){
  return JSON.parse(masterData);
 });
}

返回主JSON OK

但现在我坚持使用包含

serviceReturnJsonPromise = function() {
 return readFile(masterPath, 'utf8', err).then(function (masterData){
  var master = JSON.parse(masterData);
  var includes = [];

  _.each(master.includes, function(include) {

    var includePath = "./" + item.replace("#","");

    return readFile(includePath, 'utf8', err).then(function (includeData){
      includes.push(JSON.parse(includeData));
    });
  });
 });
}

您可以看到它还没有完成,但是由于promise arent堆积了,所以该位不起作用。我知道我将如何使用全部来堆叠承诺,但是我不知道在我读完本书之后将包含什么。

如果大家能给我任何学习节点的好起点,并保证我会很感激。

2 个答案:

答案 0 :(得分:1)

当您尝试阅读包含并且不等待结果时错误。在读取第一个包含文件之前,promise将使用零数据进行解析。

这应该有效:

serviceReturnJsonPromise = function () {
    return readFile(masterPath, 'utf8', err)
        .then(function (masterData) {
            var master = JSON.parse(masterData);

            // map over includes array and return "read" promises
            var includes = master.includes.map(function (item) {
                var includePath = "./" + item.replace("#", "");

                return readFile(includePath, 'utf8', err).then(function (includeData) {
                    return JSON.parse(includeData)
                });
            });

            // wait for all file reads
            return Promise.all(includes).then(jsons=>{
                master.includes = jsons;
                return master;
            })
        });
}

有一个不错的youtube video,其中已经说明了承诺。

P.S。也请查看该频道,其中有很多解释清楚的js主题。

答案 1 :(得分:0)

@EricP由于您只想使用json导入,因此可以直接require使用它们,而无需使用fs模块。会这样-

const path = require('path')
const main = require(path.resolve('main.json'))

const readFile = (children) => {
  const result = children.map((file) => {
    const child = require(path.resolve(file))
    if(child.includes){
      child.includes = readFile(child.includes)
    } 
    return child
  })
  children.includes = result
  return result;
}

console.dir(readFile(main.includes), {depth: null})

说明

readFile实用程序(可以更好地命名),以递归方式解析包含树并将结果重新设置。

希望这会有所帮助。