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

问题描述 投票:0回答:2

我正在努力如何在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])
node.js bluebird
2个回答
0
投票

你的问题和样本看起来很矛盾。问题是,您需要使用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来完成。


0
投票

改变这个:

 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

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

© www.soinside.com 2019 - 2024. All rights reserved.