使用async / await进行并行调用的正确方法

时间:2017-12-25 11:13:56

标签: node.js bluebird

我正在努力如何在nodejs中正确地做到这一点。这试图并行做两件事:

  • 使用axios下载网页
  • 创建目录

完成后:

  • 将结果异步保存到de created目录中的文件

然后等到完成



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])




2 个答案:

答案 0 :(得分:0)

你的问题和样本看起来很矛盾。问题是,您需要使用async和await来进行并行调用,但是示例代码显示您需要顺序调用而不是并行调用。

最好使用Async / Awaits进行顺序调用。

异步功能是“承诺”的一种简写功能,如果事情是隐含的,就像返回一样会被视为“解决”。

等待应始终位于异步功能中,在需要等待的功能上添加等待,然后再继续操作。

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来完成。

答案 1 :(得分:0)

改变这个:

 writeFile(path.join(__dirname, folderName, 'file.html'), r.data);

到此:

return writeFile(path.join(__dirname, folderName, 'file.html'), r.data);

您需要从writeFile返回承诺,以便将其添加到链中,以便您从fetchPage()返回的承诺链接到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

请注意,我删除了几个asyncawait的案例,因为它们并不需要。在await fetchPage()结束时,downloadPage()并没有为你做任何好事。从时间的角度来看,这与return fetchPage()完全相同,这样,您实际上使用fetchPage()的已解析值进行解析,这可能更有用。在downloadPage()中似乎没有任何理由使用异步或等待。请记住,async函数仍然返回一个promise,该函数的调用者仍然必须对该函数的返回值使用.then()await。因此,在await内部downloadPage()使用{{1}}并不会改变调用方的内容。

相关问题