Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/444.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用循环进行异步和等待_Javascript_Node.js - Fatal编程技术网

Javascript 使用循环进行异步和等待

Javascript 使用循环进行异步和等待,javascript,node.js,Javascript,Node.js,我有一个用JavaScript编写的小代码,可以获取html页面的内容,然后对它们进行处理(爬虫)。 问题是请求导致异步执行。 我尝试使用Promissions和async&await,但在异步执行时仍然遇到同样的问题,原因是我想一次抓取多个页面,以便移动到下一个目标。 这里有一个类似的代码: const rootlink= 'https://jsonplaceholder.typicode.com/posts/'; async function f (){ await f1()

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

const rootlink= 'https://jsonplaceholder.typicode.com/posts/';

async function f (){
    await f1()
    f3()
}

async function f1(){
    return new Promise(async (resolve,reject)=>{
        log('f1 start');
         for(let i=1;i<11;i++){
            await request(rootlink+i,(err, res,html)=>{
                if(!err && res.statusCode==200){
                    log('link '+i +' done');
                    resolve();
                }
                else reject()
            })
        }
    })
}

function f3(){
    console.log('f3')
}

f()
constrootlink='1〕https://jsonplaceholder.typicode.com/posts/';
异步函数f(){
等待f1()
f3()
}
异步函数f1(){
返回新承诺(异步(解析、拒绝)=>{
日志(“f1开始”);
for(设i=1;i{
如果(!err&&res.statusCode==200){
日志('link'+i+'done');
解决();
}
否则拒绝()
})
}
})
}
函数f3(){
console.log('f3')
}
f()
结果应该是: f1起点 链接1完成 链接2完成 链接3完成 链接4完成 链接5完成 链接6完成 链接7完成 链接8完成 链接9完成 链接10完成 f3

而不是 f1起点 链接1完成 f3 链接2完成 链接3完成 链接4完成 链接5完成 链接6完成 链接7完成 链接8完成 链接9完成
link 10 done

如果您想并行执行多个非同步操作,您实际上不想等待它们,因为这会阻塞您的功能

首先,我认为最好找到一个使用承诺的HTTP库。您使用的那个有回调,但我相信
request
项目也有一个
request-promise
包,它更易于使用

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

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');
     }
  }
}
const request=require('request-promise');
异步函数f1(){
日志(“f1开始”);

对于(设i=1;i我的问题的答案是使用来自的同步请求'sync request'
注意:我会使用一个同构的fetch包来创建可以在多个环境中使用的代码。即使您不打算在浏览器中使用它,熟悉API对将来的使用也是非常有益的。至少,这个想法让我可以编写一个代码片段,您可以在StackOverflow上实际运行

是你的答案不管你使用什么软件包。你只需等待所有承诺都得到解决,然后按照你的逻辑:

//const fetch=require('node-fetch')
常量fetchData=(…args)=>fetch(…args)。然后(r=>{
如果(!r.ok)抛出新错误('Error!')
返回r.json()
})
const getAllPostsAsync=(postIds)=>Promise.all(
map(postId=>fetchData(`https://jsonplaceholder.typicode.com/posts/${postId}`)
)
;(异步()=>{
const posts=await getAllPostsAsync([1,2,3,4,5,6,7,8,9,10])
//TODO:在等待加载所有帖子之后,这里是您的逻辑
控制台日志(posts)

})()
似乎您想要实现的不是真正的异步,您可能希望执行同步请求,而不是执行同步请求是的,这就是我真正想要的
返回新承诺(异步(…
有点奇怪。为什么不只
返回(异步(…)=>{…})()
。可能实际上不会改变任何东西,但是删除不必要的代码和缩进对调试来说从来都不是坏事。看看这个:谢谢你先生的回答。问题是在我的情况下,我必须在同步操作中这样做,以便稍后将结果存储到文件中。现实我的第二个函数(f2)根据第一个函数(f1)给出的结果进行爬网。然后还有另一个函数在两个预览函数完成其工作时存储结果。此软件包警告“您不应在生产应用程序中使用此功能”。我建议不要将
同步请求作为您的解决方案来解决。是的,我看到了这个警告。在我找到更好的解决方案之前,这是我目前唯一的解决方案(我会想出另一种避免同步操作的方法)
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');
  }
}