Javascript/NodeJ使用不同的异步函数生成一个大json文件

Javascript/NodeJ使用不同的异步函数生成一个大json文件,javascript,arrays,json,node.js,asynchronous,Javascript,Arrays,Json,Node.js,Asynchronous,我就是搞不懂。我有一个文件夹,里面有文件。我想用这些文件的信息创建一个json。确切地说,是文件名、文件名的正则版本以及我从ajax调用中获得的其他数据 每个部件都工作得很好。事实上,如果我同步运行我的代码,我将得到我想要的结果。大概是这样的: [ { "filename" : "first file", "regexname" : "first file", "ajaxresult" :

我就是搞不懂。我有一个文件夹,里面有文件。我想用这些文件的信息创建一个json。确切地说,是文件名、文件名的正则版本以及我从ajax调用中获得的其他数据

每个部件都工作得很好。事实上,如果我同步运行我的代码,我将得到我想要的结果。大概是这样的:

 [
          { 
              "filename" : "first file",
              "regexname" : "first file",
              "ajaxresult" : "first file"
          },
          { 
              "filename" : "second file",
              "regexname" : "second file",
              "ajaxresult" : "second file"
          },
 ]
但我想异步执行,因为我使用的XHR模块在尝试“同步”执行所有操作时不能正常工作,而且它当然会阻塞,尤其是在有大量文件的情况下。 我的“同步”代码如下所示(稍微简化以缩短代码)

我试图将ajaxcall包装成一个承诺,但我丢失了承诺中的文件名和regexname。像这样:

  fs.readdir(datapath, function(err, files) { 
    var data = new Array();
        if(err) throw err;
        files.forEach(function(file){
            var filename = file
            , regex= filename.replace(/regex/)/i, "")
            , filepath = './public/config/dataconfig.js'
            , mapFiles = null

        // Make promise for async call with a url composed of the regex
        var promise = getFile(url);
        promise.then( function(result) {
             mapFiles = { filename:filename, regexname:regex, ajaxcall:result}
             data[data.length] = mapfiles;
                 var JSONdata= JSON.stringify(data, null, 4);
                 fs.writeFile(filepath, JSONdata, function(e) {
                    if (!e) {
                          console.log('Done')
                     }else{ 
                          console.log('Failed', e)   
                     };
                  });
            }); 
  });
这给了我以下结果:

 [
          { 
              "filename" : "first file",
              "regexname" : "first file",
              "ajaxresult" : "first file"
          },
          { 
              "filename" : "first file",
              "regexname" : "first file",
              "ajaxresult" : "second file"
          },
 ]
所以我最后的想法是使用类似于节点异步模块的东西。在收到函数回调后编写json。但我也不能让它起作用

提前谢谢

[编辑-我忘记提及的内容]

我忘记提到的一件事是AjaxCall url是用正则表达式构建的。 比如说:

      url = 'http://www.test.com/'+regex
因此,这(在我看来)意味着我在调用ajaxcall之前执行正则表达式,但在调用之后,我还需要正则表达式来编写Json。我希望这是有意义的

[编辑2-更多信息]

我的XHR调用如下所示(没有错误的promise解决方案。在这种情况下,我返回带有结果的promise):


如果您的问题是获取文件名和正则表达式,那么将它们绑定到回调函数如何 像

然后


下面是一个快速示例,如您所述:

doStuffWithFiles('folder', 'output.json', function () {
  console.log('Done!');
});

function doStuffWithFiles (dirPath, outputFilePath, callback) {
  fs.readdir(dirPath, function (error, files) {
    async.map(
      files,
      function (file, callback) {
        doAjaxStuff(file, function (error, ajaxResults) {
          callback(null, {
            filename:    file,
            regexStuff:  file.replace(/stuff/, ''),
            ajaxResults: ajaxResults
          });
        });
      },
      function (error, results) {
        var data = JSON.stringify(results);
        fs.writeFile(outputFilePath, data, function (error) {
          callback();
        });
      }
    );
  });
}

关键部分是
async.map
,它的作用类似于,只是它要求您将结果作为参数返回给传递给第一个函数的回调。一旦所有回调都返回,
async.map
调用第二个函数,并将结果列表传递给它。

基于承诺的解决方案将正常工作,可能如下所示:

readdir(datapath).map(function (file) {
  return getFile(url)(function (ajaxresult) {
    return writeFile('./public/config/dataconfig.js', JSON.stringifiy({
      filename: file,
      regexname: file.replace(/regex/i, ""),
      ajaxcall: ajaxResult
    }, null, 4));
  });
}).end(function () {
  console.log("All done");
}, function (e) {
  console.log("Failed", e);
});
在本例中,我使用了promise实现,要使其工作,您需要确保所有异步函数都返回promise。使用Deliver.promisify可以轻松转换典型的回调函数:

var promisify = require('deferred').promisify;
var readdir = promisify(fs.readdir);
var writeFile = promisify(fs.writeFile);

你需要在node.js中使用承诺吗?老实说,我不知道,我从来没有用过它来回答这个问题。这几乎正是我所需要的。只有一件事我忘了提;“doAjaxStuff”在url中使用“regexStuff”。举个例子:url='。doAjaxStuff函数将如下所示:getInfo(url,function(error,result)){当然我不想重复正则表达式两次。再次感谢!感谢您的回答。我想我只是看不到它,但这给了我一个“失败的[TypeError:Caonnot read null属性“0”)。但我不知道它从何而来。XHR调用只给了我一次正确的数据(这让我感到奇怪)。Vpml可以在运行时显示完整的错误堆栈跟踪或代码吗?错误是由getFile引起的,它应该返回promise,但它尝试从null属性获取索引(因此“无法读取null的属性“0”)。以下操作应该有效:我讨厌占用您这么多时间。感谢迄今为止的所有帮助,但很遗憾。我收到以下错误:失败[TypeError:Object#没有方法‘Stringify’]。但我不明白为什么会出现此错误,因为文件、电影字幕和scraperresults似乎都不会导致此错误,也不会导致添加的延迟。我看不出原因。再次感谢!Vprnl,错误消息是一个最好的提示,有一个输入错误,应该是“stringify”而不是“stringifyi”;-)
promise.then(callback.bind({'filename':filename,'regex':regex}))
doStuffWithFiles('folder', 'output.json', function () {
  console.log('Done!');
});

function doStuffWithFiles (dirPath, outputFilePath, callback) {
  fs.readdir(dirPath, function (error, files) {
    async.map(
      files,
      function (file, callback) {
        doAjaxStuff(file, function (error, ajaxResults) {
          callback(null, {
            filename:    file,
            regexStuff:  file.replace(/stuff/, ''),
            ajaxResults: ajaxResults
          });
        });
      },
      function (error, results) {
        var data = JSON.stringify(results);
        fs.writeFile(outputFilePath, data, function (error) {
          callback();
        });
      }
    );
  });
}
readdir(datapath).map(function (file) {
  return getFile(url)(function (ajaxresult) {
    return writeFile('./public/config/dataconfig.js', JSON.stringifiy({
      filename: file,
      regexname: file.replace(/regex/i, ""),
      ajaxcall: ajaxResult
    }, null, 4));
  });
}).end(function () {
  console.log("All done");
}, function (e) {
  console.log("Failed", e);
});
var promisify = require('deferred').promisify;
var readdir = promisify(fs.readdir);
var writeFile = promisify(fs.writeFile);