我正在努力如何在nodejs中正确地做到这一点。这试图并行做两件事:
完成后:
然后等到完成
const uuidv1 = require('uuid/v1')
const fs = require('fs')
const util = require('util')
const axios = require('axios')
const path = require('path')
const mkdir = util.promisify(fs.mkdir)
const writeFile = util.promisify(fs.writeFile)
const downloadPage = async (url='http://nodeprogram.com') => {
console.log('downloading ', url)
const fetchPage = async function() {
const folderName = uuidv1()
return axios
.all([
mkdir(folderName),
axios.get(url)
])
.then(axios.spread(function (f, r) {
writeFile(path.join(__dirname, folderName, 'file.html'), r.data);
}));
}
await fetchPage()
}
downloadPage(process.argv[2])
你的问题和样本看起来很矛盾。问题是,您需要使用async和await来进行并行调用,但是示例代码显示您需要顺序调用而不是并行调用。
最好使用Async / Awaits进行顺序调用。
async函数是'Promise'的一种简写函数,事情是隐式完成的,就像返回一样会被视为'resolve'。
await应始终在异步函数内,在继续进行之前添加等待您需要等待的函数。
await函数中的语法更改是,而不是
somePromiseFunctionCall().then( (someVarible) => {...}).catch(e => {})
你需要使用
const asyncFunction = async (parameters) => {
try {
// First Function call that returns Promise / async
someVariable = await somePromiseFunctionCall();
// Second (sequential) call that returns Promise / async
someNewVariable = await someotherPromiseFunctionCall();
} catch(e) {
throw new Error(e);
}
}
现在,在您的示例中,如果您的要求是等待axios返回然后创建文件夹然后将结果写入文件,则可以使用async和await来完成。
改变这个:
writeFile(path.join(__dirname, folderName, 'file.html'), r.data);
对此:
return writeFile(path.join(__dirname, folderName, 'file.html'), r.data);
您需要从writeFile返回promise,以便将其添加到链中,以便从fetchPage()
返回的promise将链接到writeFile()
操作。正如您的代码最初,writeFile()
操作正在进行,并且根本没有与您从fetchPage()
返回的承诺相关联,因此当您执行以下操作时:
await fetchPage()
它没有等待writeFile()
操作。
清理后的版本可能如下所示:
const downloadPage = (url='http://nodeprogram.com') => {
console.log('downloading ', url)
// don't really need this separate fetchPage() function
const fetchPage = function() {
const folderName = uuidv1()
return axios
.all([
mkdir(folderName),
axios.get(url)
])
.then(axios.spread(function (f, r) {
return writeFile(path.join(__dirname, folderName, 'file.html'), r.data);
}));
}
return fetchPage()
}
然后,你会像这样使用它:
downloadPage().then(() => {
// page is downloaded now
});
或者,在async
函数中,您可以:
await downloadPage();
// page is downloaded here
请注意,我删除了几个async
和await
的案例,因为它们不需要。 await fetchPage()
在downloadPage()
结束时对你没有任何好处。从时间的角度来看,这与return fetchPage()
完全相同,这样,你实际上正在解决fetchPage()
的解析值,这可能更有用。在downloadPage()
中似乎没有任何理由使用异步或等待。请记住,async
函数仍然返回一个promise,该函数的调用者仍然必须在该函数的返回值上使用.then()
或await
。因此,在await
中使用downloadPage()
不会改变调用者的内容。