Javascript 如何处理异步循环?
我目前正在从事一个项目,以基于lunr.js的JavaScript实现全文搜索客户端 问题是,我正在努力构建然后保存索引,因为我有几个异步调用Javascript 如何处理异步循环?,javascript,node.js,asynchronous,lunrjs,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 = [], ig
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);
});
};
提前感谢。有四个问题:
- 您的函数
不会buildIndex
返回承诺,因此调用它时不能等待结果
- 遇到目录时,递归调用
,但不要像在else情况下使用buildIndex
那样等待结果promesse
- 你有
promeses.push(promesse)仅在读入文件后执行的异步回调内的代码>调用。将承诺放入数组的想法是正确的,但您必须立即这样做,以便它在
promise之前发生
- 由于某种原因,您从代码中删除了
Promise.all
function buildIndex(…) {
…
var promises = paths.map(function(path) {
if (isDir(path)) {
return buildIndex(…);
} else {
return JSDOM.fromFile(…).then(…);
}
});
return Promise.all(promises).then(…);
}
使用forEach并不是一个正确的选择,因为人们想要回报承诺。 因此,更明智的做法是使用.map,然后在if/else语句中返回承诺。 最后,我们必须称之为承诺。所有(承诺)都在做出。然后(…)按预期使用 我的最后一项职能:
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的回答和帮助。您不是在等待递归调用的结果-它不会返回承诺,您也不会将其放入数组中。@DNZLL是
rawIndex。是否添加
异步调用?@Bergi确实如此。我不知道如何正确地实现它。@JamshidAsadzadeh好吧,我不这么认为,至少文档中没有提到它:。我更愿意说问题与$('h1,h2,h3,h4,h5,h6')有关。循环中的每个()和循环。@DNZZ将您的编辑设置为3会使代码变得更糟。我不介意你把它放回去。非常感谢你从一个新的JS学习者那里抽出时间,它似乎工作得很好。