到目前为止,这是我的javascript代码:
文件是指向html文件的路径数组
我希望h3s成为html文件的所有h3s标签的数组。
function getH2OfFiles(files) {
return new Promise((resolve, reject) => {
let h3s = [];
for (let i = 0; i < files.length; i++) {
fs.readFile(path.join(__src, 'documentation', files[i]), 'utf8', (err, data) => {
if (err) throw err;
if (data.match(/<h3>(.*)<\/h3>/)) {
//console.log("->", { file: files[i], h3: data.match(/<h3>(.*)<\/h3>/)[1] })
h3s.push(data.match(/<h3>(.*)<\/h3>/)[1]);
}
})
}
resolve(h3s);
});
}
它似乎不适用于for循环(因为它是异步的),但它是如何实现的?
答案 0 :(得分:2)
承诺世界中ConfigurableApplicationContext
循环的副本for
,通常与Promise.all
结合使用。在您的情况下,编写一个处理一个文件的函数,例如
.map
然后将其应用于文件列表:
function getH3OfFile(fileName) {
return new Promise((resolve, reject) => {
fs.readFile(path.join('.....', fileName), 'utf8', (err, data) =>
err
? reject(err)
: resolve(data.match(/<h3>(.*)<\/h3>/))
);
});
}
(万一你不知道,还有let fileNames = [...]
Promise
.all(fileNames.map(getH3OfFile))
.then(h3s => ...) // h3s is an array of matches
)。
答案 1 :(得分:1)
你大部分时间都在那里,你只需要跟踪你已经获得了多少回调,并等待你解决这些问题。另外,如果出现问题,请使用reject(err)
而不是throw err
:
function getH2OfFiles(files) {
return new Promise((resolve, reject) => {
let h3s = [];
let complete = 0;
for (let i = 0; i < files.length; i++) {
fs.readFile(path.join(__src, 'documentation', files[i]), 'utf8', (err, data) => {
if (err) reject(err); // ***
const match = data.match(/<h3>(.*)<\/h3>/);
if (match) { // ***
h3s.push(match[1]);
}
if (++complete === files.length) { // ***
resolve(h3s); // ***
} // ***
})
}
});
}
(请注意,我还将第一次调用的结果保存到match
,而不是让正则表达式运行两次。)
但是,请注意您可以不按顺序接收这些完成,因此h3s
可能与文件无关(如果重要)。
或者通过分而治之的方式进行简化并给自己一个承诺版本的readFile
,然后通过Promise.all
读取所有文件后构建结果:
function readFilePromise(path, encoding) {
return new Promise((resolve, reject) => {
fs.readFile(path, encoding, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
function getH2OfFiles(files) {
return Promise.all(files.map(file => readFilePromise(path.join(__src, 'documentation', file), 'utf8')))
.then(results => {
const h3s = [];
results.forEach(result => {
const match = data.match(/<h3>(.*)<\/h3>/);
if (match) {
h3s.push(match[1]);
}
});
return h3s;
});
}
这也有一个好处,Promise.all
可确保您以与原始承诺数组相同的顺序接收数组(如果重要)。
(注意:有些lib将为您提供Promise-ify NodeJS API。)
答案 2 :(得分:0)
使用async npm模块。它们提供同步迭代方法以及控制流的不同方法,如系列,瀑布,并行等。