0

诚然,我是节点的新手,但看起来这应该可以正常工作。我正在使用多方解析一个表单,该表单返回一个数组。然后我使用 for each 来遍历数组。但是 - for each 不等待内部代码执行。不过,我有点困惑为什么它不是。

var return_GROBID =  function(req, res, next) {
  var form = new multiparty.Form();

  var response_array = [];
  form.parse(req, function(err, fields, files) {

    files.PDFs.forEach(function (element, index, array) {
      fs.readFile(element.path, function (err, data) {
        var newPath = __dirname + "/../public/PDFs/" + element.originalFilename;
        fs.writeFile(newPath, data, function (err) {
          if(err) {
            res.send(err);
          }
          GROBIDrequest.GROBID2js(newPath, function(response) {
            response_array.push(response);
            if (response_array.length == array.length) {
                res.locals.body = response_array;
                next();
            }
          });
        });
      });
    });
 });
}

如果有人能给我一些关于正确方法的见解,那就太好了。

编辑:谜团仍在继续。我在另一台机器上运行了这段代码,它工作正常。到底是怎么回事?为什么一台机器与另一台机器不一致?

4

1 回答 1

-2

我猜PDFs.forEach你只是在调用内置的 forEach 函数,对吗?

在 Javascript 中,很多事情都是异步的——这意味着:

linea();
lineb();

lineb 可能在linea完成它开始的任何操作之前执行(例如,因为在异步编程中,我们不会等到网络请求返回)。

这与其他编程语言不同:大多数语言将“阻塞”直到linea完成,即使linea可能需要时间(例如发出网络请求)。(这称为同步编程)。

完成序言后,回到你原来的问题:

forEach同步函数也是如此。如果你像下面这样重写你的代码,它会起作用(但没有用):

 PDFs.forEach(function (element, index, array) {
   console.log(element.path)
 }

(console.log 是 Javascript 中罕见的同步方法)。

但是在你的forEach 循环中你有fs.readFile. 注意最后一个参数,一个函数?操作完成后,Node 将回调该函数(回调)。

您的代码将当前,如所观察到的那样,点击 fs.readFile,说“好的,下一件事”,然后转到循环中的下一项。

解决此问题的一种方法是使用异步库,并且更改代码最少。

async.forEachOf(PDFs, function(value, key, everythingAllDoneCallback) {

 GROBIDrequest.GROBID2js(newPath, function(response) {
        response_array.push(response);
        if (response_array.length = array.length) {
          ...
        }

        everythingAllDoneCallback(null)

});

使用此代码,您将完成所有异步工作,然后在可以安全移动到列表中的下一项时触发回调。

像这样的 Node 和回调是一种非常常见的 Node 模式,它应该被 Node 上的初学者材料很好地涵盖。但它是 Node 开发中最……意想不到的概念之一。

我在这方面找到的一个资源是(一组课程中的一个)关于NodeJS For Beginners: Callbacks。这个,以及使用阻塞(同步)和非阻塞(异步)函数,希望这个 SO 答案可以提供一些启示:)

于 2018-01-07T19:16:43.867 回答