如何处理异步循环?

时间:2017-07-27 14:46:20

标签: javascript node.js asynchronous lunrjs

我目前正在开发一个基于lunr.js在JavaScript中实现全文搜索客户端的项目。

问题是,我正在努力构建然后保存索引,因为我有几个异步调用。

    function buildIndex(rawIndex, root, indexPath = root + 'js/app/index.json') {
  var path = path || require('path');
  var fs = fs || require('fs'),
    promesses = [],
    ignore = ['node_modules'],
    files = fs.readdirSync(root);
  files.forEach(function (file) {

    if (fs.statSync(path.join(root, file)).isDirectory() && ignore.indexOf(file) == -1) {
      buildIndex(rawIndex, path.join(root, file), indexPath);
    }
    else if (file.substr(-5) === '.html' && file != 'example.html') {
      var promesse = JSDOM.fromFile(path.join(root, file)).then(dom => {

        var $ = require('../lib/_jquery')(dom.window);
        populate();
        console.log(file + " indexé");
        function populate() {
          $('h1, h2, h3, h4, h5, h6').each(function () {
            var title = $(this);
            var link = path.join(root, file).replace('..\\', '') + "#" + title.prop('id');
            var body = title.nextUntil('h1, h2, h3, h4, h5, h6');
            rawIndex.add({
              id: link,
              title: title.text().latinise(),
              body: body.text().latinise()
            });
          });
        };
      });
      promesses.push(promesse);
    }
  });
  Promise.all(promesses)
    .then(function () {
      fs.writeFileSync(indexPath, "var data = " + JSON.stringify(rawIndex), 'utf8');
    })
    .catch(function (err) {
      console.log("Failed:", err);
    });
};

提前致谢。

2 个答案:

答案 0 :(得分:1)

有四个问题:

  • 您的函数buildIndex没有return承诺,因此在调用时无法等待结果
  • 遇到目录时,您会递归拨打buildIndex,但不要像在其他情况下使用promesse那样等待其结果。
  • 在异步回调中有promesses.push(promesse);调用,只有在读入文件后才会执行。将promise放在数组中的想法是正确的,但你必须立即执行,以便在{在数组上调用{1}}。
  • 您出于某种原因从代码中删除了Promise.all

基本上该函数应具有此通用模式:

Promise.all

答案 1 :(得分:0)

使用forEach不是正确的选择,因为想要返回Promise。 因此,更明智的做法是使用.map然后在if / else语句中返回Promises。 最后,必须调用Promises.all(promises)使.then(...)按预期使用。

我的最终功能:

function buildIndex(rawIndex, root, indexPath = root + 'js/app/index.json') {
  var path = path || require('path');
  var fs = fs || require('fs'),
    promises = [],
    ignore = ['node_modules'],
    files = fs.readdirSync(root);

  var promises = files.map(function (file) {
    if (fs.statSync(path.join(root, file)).isDirectory() && ignore.indexOf(file) == -1) {
      return buildIndex(rawIndex, path.join(root, file), indexPath);
    }
    else if (file.substr(-5) === '.html' && file != 'example.html') {
      return JSDOM.fromFile(path.join(root, file)).then(dom => {

        var $ = require('jquery')(dom.window);
        populate();
        console.log(file + " indexé");

        function populate() {
          $('h1, h2, h3, h4, h5, h6').each(function () {
            var title = $(this);
            var link = path.join(root, file).replace('..\\', '') + "#" + title.prop('id');
            var body = title.nextUntil('h1, h2, h3, h4, h5, h6');
            rawIndex.add({
              id: link,
              title: title.text().latinise(),
              body: body.text().latinise()
            });
          });
        };
      })
    }
  })
  return Promise.all(promises).then(function () {
    fs.writeFileSync(indexPath, "var data = " + JSON.stringify(rawIndex), 'utf8');
  });
};

感谢@Bergi的回答以及那些帮助过的人。