提问者:小点点

为什么for循环不想在节点js的函数上等待进程完成?


我试图创建一个脚本,使用node js从多个URL下载页面,但是循环不想等待请求完成并继续打印,我还得到了一个使用async for循环的提示,但是它仍然没有工作。

这是我的代码

function GetPage(url){
    console.log(` Downloading page ${url}`);
    request({
        url: `${url}`
    },(err,res,body) => {
        if(err) throw err;
        console.log(` Writing html to file` );
        fs.writeFile(`${url}.html`,`${body}`,(err) => {
            if(err) throw err;
            console.log('saved');
        });
    });
}
var list = [ 'https://www.someurl.com/page1.html', 'https://www.someurl.com/page2.html', 'https://www.someurl.com/page3.html' ]
const main = async () => {
    for(let i = 0; i < list.length; i++){
        console.log(` processing ${list[i]}`);
        await GetPage(list[i]);
    }
};

main().catch(console.error);

输出:

 processing https://www.someurl.com/page1.html
 Downloading page https://www.someurl.com/page1.html
 processing https://www.someurl.com/page2.html
 Downloading page https://www.someurl.com/page2.html
 processing https://www.someurl.com/page3.html
 Downloading page https://www.someurl.com/page3.html
 Writing html to file
 Writing html to file
saved
saved
 Writing html to file
saved

共1个答案

匿名用户

因为循环不等待回调完成,它将继续执行回调。您需要将getPage函数转换为promise或使用promise.all,如下所示。

var list = [
  "https://www.someurl.com/page1.html",
  "https://www.someurl.com/page2.html",
  "https://www.someurl.com/page3.html",
];

function getPage(url) {
  return new Promise((resolve, reject) => {
    console.log(` Downloading page ${url}`);
    request({ url: `${url}` }, (err, res, body) => {
      if (err) reject(err);
      console.log(` Writing html to file`);
      fs.writeFile(`${url}.html`, `${body}`, (writeErr) => {
        if (writeErr) reject(writeErr);
        console.log("saved");
        resolve();
      });
    });
  });
}

const main = async () => {
  return new Promise((resolve, reject) => {
    let promises = [];
    list.map((path) => promises.push(getPage(path)));
    Promise.all(promises).then(resolve).catch(reject);
  });
};

main().catch(console.error);