在Node.js和Puppeteer中,async / await按顺序运行异步函数

3

问题

我有3个函数彼此依赖,因此我希望它们按顺序运行。这些函数是异步的,返回promise并需要一定时间才能运行。

我的代码 - Index.js

#Function One
scrapA.scrap().then(data => {
    readWriteToFile.writeToFile(data, 'scrapA-data-'+timestamp, 'json');
});

#Function Two
compare.compareData('./output/json/data.json', './output/json/scraped-data-'+timestamp+'.json').then(data => {

    let dataWithStockData = data;
    let mapDatas = dataWithStockData.map( obj => { 

        let finalObj = {
            manufacturer: obj.manufacturer,
            grade: obj.condition,
            carrier: obj.carrier,
            stock: obj.stock,
        }
        return finalObj;
    });

#Function Three
readWriteToFile.writeToFile(data, 'data-with-stock-'+timestamp, 'csv'); });

我的代码 - compare.js

async function compareData(models, competitorsData) {

try {
    
    const modelsArr = JSON.parse(fs.readFileSync(models, { encoding: 'utf8', flag: 'r' }));
    const competitorsDataArr = JSON.parse(fs.readFileSync(competitorsData, { encoding: 'utf8', flag: 'r' }));

    //Loop through both array of json data
    modelsArr.forEach((device, deviceKey) => {

        competitorsDataArr.forEach((scrapedData, scrapedDataKey) => {

            
            if (
                    scrapedData.manufacturer.toLowerCase() === data.manufacturer.toLowerCase()
            ) {

                 modelsArr[dataKey]['stk'] = scrapedData.stk;

            }
        })
    });

    return modelsArr;

} catch (error) {

    console.log("Error", error);
    throw error;
}

}

My Code - readWriteToFile.js

async function writeToFile(data, filename, type) {

let finalData = '';

if (type == "json") {

    finalData = JSON.stringify(data);

} else if (type == "csv") {

    finalData = arrayToCSV(data);

} else {
    console.log("File type not supported");
    process.exit(1);
}

fs.writeFile("./output/" + type + '/' + filename + '.' + type, finalData, (err) => {
    if (err) {
        console.log(err);
    } else {
        console.log("File written successfully\n");
    }
});

我的解决方案

我的解决方案

我只是简单地在所有的函数调用中添加了async并在前面加上了await。它没有起作用,也没有抛出任何错误。

(async () => {
    
    await scraperA.scrap().then(data => {
            console.log("DATA", data);
            readWriteToFile.writeToFile(data, 'scraped-data-'+timestamp, 'json');
        });
    
    await compare.compareData('./output/json/data.json', './output/json/scraped-data-'+timestamp+'.json').then(data => {
        let dataWithStockData = data;
        mapData = dataWithStock.map( obj => { 
    
            let finalObj = {
                manufacturer: obj.manufacturer,
                grade: obj.condition,
                stock: obj.stock,
            }
            return finalObj;
        });
    });

    await readWriteToFile.writeToFile(mapData, 'data-with-stock-'+timestamp, 'csv');

});

预期结果是什么?你的解决方案中是否声明了mapData(如果有的话)? - Fre Timmerman
2
你没有调用函数。你必须调用函数才能创建一个异步IIFE - jabaa
1
如果您没有添加依赖项的限制,async库提供了一种非常好的方式来管理这些东西。 在您的情况下,我认为使用瀑布方法是合适的,它使您能够将一个调用的结果数据用于另一个调用,如文档中所述。 - MatteoPHRE
@jabaa 添加了来自其他文件的代码。 - Murlidhar Fichadia
@FreTimmerman,最终目标是按顺序运行三个部分:1)将抓取的数据写入文件,2)比较两个文件中的数据,3)获取匹配的数据并写入CSV文件。 - Murlidhar Fichadia
显示剩余6条评论
2个回答

2
代码结构
(async () => {
    
    /* your code */

});

建议您想要创建一个异步的立即调用函数表达式(IIFE)。但是您必须调用它(在末尾加上()):
(async () => {
    
    /* your code */

})();

使用当前版本的Node.js,您不需要异步IIFE。Node.js支持顶层等待

由于readWriteToFile.writeToFilecompare.compareData不返回Promise,因此您无法调用.then,也没有意义使用await

从Node.js v14.8开始,您可以编写:

await scraperA.scrap().then(data => {
    console.log("DATA", data);
    readWriteToFile.writeToFile(data, 'scraped-data-'+timestamp, 'json');
});

const dataWithStockData = compare.compareData('./output/json/data.json', './output/json/scraped-data-'+timestamp+'.json')
mapData = dataWithStock.map( obj => { 

    let finalObj = {
        manufacturer: obj.manufacturer,
        grade: obj.condition,
        stock: obj.stock,
    }
    return finalObj;
});

readWriteToFile.writeToFile(mapData, 'data-with-stock-'+timestamp, 'csv');

在你修复问题后,你可以考虑使用 .then 或者 await/async 来清理你的代码。混用它们通常被认为是不好的代码风格。
const data = await scraperA.scrap();
console.log("DATA", data);
readWriteToFile.writeToFile(data, 'scraped-data-'+timestamp, 'json');

const dataWithStockData = compare.compareData('./output/json/data.json', './output/json/scraped-data-'+timestamp+'.json');

mapData = dataWithStock.map( obj => { 

  let finalObj = {
    manufacturer: obj.manufacturer,
    grade: obj.condition,
    stock: obj.stock,
  }
  return finalObj;
});

readWriteToFile.writeToFile(mapData, 'data-with-stock-'+timestamp, 'csv');

2

如果不知道你调用的哪些函数是同步的,很难回答。但是做出以下假设:

  • readWriteToFile.writeToFile返回一个Promise(或它是异步的)
  • mapData在其他地方定义

你必须:

  • 在第一个.then(...)块的最后一行添加一个return语句
  • 如jabaa所说,你必须实际调用该函数。
(async () => {
    
    await scraperA.scrap().then(data => {
            console.log("DATA", data);
            return readWriteToFile.writeToFile(data, 'scraped-data-'+timestamp, 'json');
        });
    
    await compare.compareData('./output/json/data.json', './output/json/scraped-data-'+timestamp+'.json').then(data => {
        let dataWithStockData = data;
        mapData = dataWithStock.map( obj => { 
    
            let finalObj = {
                manufacturer: obj.manufacturer,
                grade: obj.condition,
                stock: obj.stock,
            }
            return finalObj;
        });
    });

    await readWriteToFile.writeToFile(mapData, 'data-with-stock-'+timestamp, 'csv');

})();

抱歉我的错误,“compare.compareData()”调用不是异步的,也不是“readWriteToFile.writeToFile()”。让我展示另外两个文件中的代码。 - Murlidhar Fichadia
看到其他的代码,虽然函数内部没有异步内容(只有同步代码),但你将它们标记为async使它们变成了异步函数。因此,它们返回一个Promise,你仍然需要等待它们完成。我认为解决方案(在第一次调用writeToFile之前添加return)仍然适用。它起作用了吗?给个反馈是很好的。 - Jaime Blázquez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接