异步并等待循环

时间:2019-10-28 17:30:06

标签: javascript node.js

我有一个用JavaScript编写的小代码,可以获取html页面的内容,然后对它们进行处理(搜寻器)。 问题是 请求 导致异步执行。 我尝试使用Promises和async&await,但是仍然遇到异步执行相同的问题,原因是我想一次抓取多个页面以便移至下一个目标。 这是我在这里的类似代码:

   pack  a_cost  b_cost
0     2    10.5    5.25
1     2    12.0    6.00
2     2    11.0    5.50
3     2    13.0    6.50

结果应为: F1开始 链接1完成 链接2完成 链接3完成 链接4完成 链接5完成 链接6完成 链接7完成 链接8完成 链接9完成 链接10完成 f3

而不是 F1开始 链接1完成 f3 链接2完成 链接3完成 链接4完成 链接5完成 链接6完成 链接7完成 链接8完成 链接9完成 链接10完成

3 个答案:

答案 0 :(得分:1)

注意:我将使用node-fetch之类的同构提取包来创建可在多种环境中使用的代码。即使您不打算在浏览器中使用它,熟悉API也会对将来的使用非常有益。至少,这个主意使我能够编写一个可以在StackOverflow上实际运行的代码段。

不过,无论使用哪种软件包,都

Promise.all() 是您的答案。您只需等待所有诺言解决,然后执行您的逻辑即可:

// const fetch = require('node-fetch')

const fetchData = (...args) => fetch(...args).then(r => {
  if (!r.ok) throw new Error('Error!')
  return r.json()
})

const getAllPostsAsync = (postIds) => Promise.all(
  postIds.map(postId => fetchData(`https://jsonplaceholder.typicode.com/posts/${postId}`))
)

;(async () => {
  const posts = await getAllPostsAsync([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
  
  // TODO: Your logic here, after waiting for all posts to load
  console.log(posts)
})()

答案 1 :(得分:0)

鉴于您想并行执行多个异步操作,您实际上并不想await,因为这会阻塞您的功能。

首先,我想说的是找到一个使用Promise的HTTP库更好。您使用的一个具有回调,但是我相信request项目还具有一个request-promise软件包,它更易于使用。

这是f1函数的固定版本,可以更正确地使用promise。请注意,这还没有并行化。

const request = require('request-promise');

async function f1(){
  log('f1 start');
  for(let i=1;i<11;i++){
     const res = await request(rootlink+i);
     if(res.statusCode==200){
        log('link '+i +' done');
     }
  }
}

这里是此函数的另一个版本,只是现在已经完全并行化了。

async function f1(){
  log('f1 start');
  const promises = [];
  for(let i=1;i<11;i++){
     promises.push(
       request(rootlink+i).then( (res) => {
         if(res.statusCode==200){
           log('link '+i +' done');
         }
       })
     );
  }

  await Promise.all(promises);
}

如果将其拆分为多个功能,可以使它更加优雅:

async function f1(){
  log('f1 start');
  const promises = [];
  for(let i=1;i<11;i++){
     promises.push(checkLink(i));
  }

  await Promise.all(promises);
}

async function checkLink(i) {
  const res = await request(rootlink+i);
  if (res.statusCode==200){
     log('link '+i +' done');
  }
}

答案 2 :(得分:0)

我的问题的答案是使用来自的同步请求“ sync-request”  https://www.npmjs.com/package/sync-request