我有以下函数,它不会按照我想要的顺序执行。
回调中的控制台.log实际上在函数本身中的循环甚至执行之前就被触发了。所以总而言之,我希望函数"getFiles"在下一个"createDatabase"开始执行之前完全完成。
感谢您的帮助。 我已经对这个问题发疯了:(
const fs = require("fs")
let data = []
const getFiles = () => {
fs.readdir("./database/test/", (err, files) => {
files.forEach(file => {
require("../database/test/" + file)
data.push(Number(file.split(".")[0]))
console.log(data)
})
})
}
const createDatabase = () => {
data.sort((a, b) => {
return a-b
})
console.log(data)
// Do some other stuff
}
const run = async () => {
await getFiles
await createDatabase()
process.exitCode = 0
}
run()
使用较新的fs.promises
接口进行编码相当简单,因此您可以await
readdir()
输出:
const fsp = require('fs').promises;
const path = require('path');
const async getFiles = () => {
const root = "./database/test/";
let files = await fsp.readdir(root);
return files.map(file => {
require(path.join(root, file));
return Number(file.split(".")[0]);
});
}
const createDatabase = (data) => {
data.sort((a, b) => {
return a-b
})
console.log(data)
// Do some other stuff
}
const run = async () => {
let data = await getFiles();
createDatabase(data);
process.exitCode = 0
}
run().then(() => {
console.log("all done");
}).catch(err => {
console.log(err);
});
更改摘要:
- 使用 fs.promises 接口,这样我们就可以
await
readdir()
的结果。 - 将
getFiles()
更改为async
,以便我们可以使用await
,因此它会返回一个承诺,该承诺在所有异步工作完成后解析。 - 将
data
移动到函数中(从getFiles()
解析并传递给createDatabase()
(,而不是由多个函数共享的顶级变量。 - 跟踪调用
run()
的完成和错误 - 实际上在
run()
中用括号称呼getFiles()
.
以下代码片段将首先完全运行 getFiles 函数,然后运行 createDatabase 函数。对于使用 async/await,函数需要返回一个 promise(在此处阅读有关 promise 的信息(。
const fs = require("fs")
let data = []
const getFiles = () => {
return new Promise((resolve, reject) => {
fs.readdir("./database/test/", (err, files) => {
if (err) {
reject(err);
}
files.forEach(file => {
require("../database/test/" + file)
data.push(Number(file.split(".")[0]))
console.log(data)
})
resolve(true);
})
})
}
const createDatabase = () => {
data.sort((a, b) => {
return a-b
})
console.log(data)
// Do some other stuff
}
const run = async () => {
await getFiles();
await createDatabase();
process.exitCode = 0;
}
run()
由于 createDatabase 函数现在没有返回任何承诺,因此您可以删除它前面的 await。仅当返回承诺时才使用 Await。你可以在这里阅读关于async/await的信息。
该问题与对异步代码使用 forEach 循环有关。这个答案有更多关于这个问题的信息:
将 async/await 与 forEach 循环结合使用
我不太确定您到底想做什么,但看起来问题出在您的运行函数中。您没有在运行中调用 getFiles 函数。你关心的只是提到函数名称。还需要将getFiles
包装在承诺中,它应该是
const run = async () => {
await getFiles();
await createDatabase();
process.exitCode = 0
}