for循环节点中的异步js

时间:2018-10-10 20:05:17

标签: arrays node.js for-loop asynchronous

我正在尝试访问一个api,我将不得不根据需要迭代的页号多次运行api调用,以下是我正在使用的代码以及如何获得所有推送的响应放入数组。

因为nodeJs是单线程的,所以它不等待api的响应。 我该如何解决这个问题并确保所有响应值都被压入数组

在for循环中,我想要具有api响应的所有值的最终数组。因此,我检查总页值和响应页号是否匹配,这意味着将是最后一页,并且将数组推到另一个函数,但是当我这样做时,它不具有所有值,因为nodejs不等待api响应。

const fs = require('fs');
var pepKey = 'asdfasdfasd';
var pepResponse;

var pepTimecards = [];
pep();


function pep(){
    var options = {
        headers: {
            "content-type": "application/json",
        },
        agentOptions: {
            pfx: fs.readFileSync('./certificate/asdfsdaf.p12'),
            passphrase: 'asdasdsda'
        }
    };

    request.get('https://source.asdfasdf.io/api/organisations/asdfasdf/timecard_keys?timecard_type=Flex',options,  (err, res, body) => {
      if (err) { return console.log(err); }
      pepResponse = JSON.parse(body)

    pepTimecards = pepResponse.data;
      if(pepResponse.pages > 1){
         for(let i=2;i<=pepResponse.pages;i++){

            var url = 'https://source.`pepme`.io/api/organisations/sdfsadf/timecard_keys?timecard_type=Flex&page='+pageNo;
            request.get(url,options,  (err, res, body) => {
                if (err) { return console.log(err); }
                body = JSON.parse(body)
                pepTimecards = pepTimecards.concat(body.data)
                if(pepResponse.pages == body.page){
                    console.log(pepResponse.pages)
                    console.log(body.page +"body page")
                    console.log(pepTimecards)
                }
              });


        }


      }else{

      }  
    });
}

1 个答案:

答案 0 :(得分:0)

使用请求承诺库,该库提供请求库的承诺版本。然后,您可以在for循环中使用async / await来序列化您的操作:

较新的答案,可以与OP的问题中的已编辑代码一起使用

const fs = require('fs');
const rp = require('request-promise');
const pepKey = 'asdfasdfasd';

pep().then(pepTimecards => {
    // the timecard data is valid in here
    console.log(pepTimecards);
}).catch(err => {
    console.log(err);
});


async function pep() {
    let timecards = [];
    const options = {
        headers: {
            "content-type": "application/json",
        },
        agentOptions: {
            pfx: fs.readFileSync('./certificate/asdfsdaf.p12'),
            passphrase: 'asdasdsda'
        },
        json: true,
        uri: 'https://source.asdfasdf.io/api/organisations/asdfasdf/timecard_keys?timecard_type=Flex'
    };

    let pepResponse = await rp(options);

    timecards = pepResponse.data;
    if (pepResponse.pages > 1) {
        for (let i = 2; i <= pepResponse.pages; i++) {
            options.uri = 'https://source.`pepme`.io/api/organisations/sdfsadf/timecard_keys?timecard_type=Flex&page='+pageNo;
            let body = await rp(url, options);
            // add body.data onto the existing array
            timecards.push(...body.data);
        }
    } else {

    }
    console.log(pepResponse.pages)
    console.log(timecards)
    return timecards;
}

在OP编辑问题代码之前先回答

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

// I'm assuming this is some sort of method definition on a class, otherwise it needs the function keyword
async pageno(pageNo) {
    for (let i=2;i<=pepResponse.pages;i++){
        try {
            options.uri = 'https://test/timecard_keys?timecard_type=asdas&page='+pageNo;
            // let request-promise parse the json for you automatically
            options.json = true;
            let body = await rp(options);
            pepTimecards = pepTimecards.concat(body.data)
            if (pepResponse.pages == body.page){
                console.log(pepResponse.pages)
                console.log(body.page +"body page")
                console.log(pepTimecards)
            }
        } catch(e) {
            // decide what to do for error handling
            // this will log and rethrow so the caller will get a rejected promise
            console.log(e);
            throw e;
        }
    }
    // return some value here to be the resolved value of the returned promise
    return pepTimecards;
}

在您的代码中,尚不清楚声明optionspepTimecardspepResponse变量的位置。可能应该在此处将它们声明为局部变量,或者将其传递给函数和/或从函数中返回。


修改摘要:

  1. 在方法声明中添加async,以便我们可以使用await
  2. 将请求承诺库加载到rp变量中
  3. options.json = true添加到让请求承诺库自动为我们解析JSON结果
  4. 更改rp()以仅使用选项结构(向其添加URL)
  5. 添加try / catch来捕获await中的任何错误,将其记录下来,然后重新抛出,这样pageno()将返回一个承诺,如果出现错误则拒绝该行为(您可以自定义行为,错误(如果需要)
  6. 添加一个返回值,以使promise具有有意义的解析值(您不应该像现在那样使用副作用编程(修改未传入,本地声明或返回的变量)。

您仍需要解决的问题:

  1. 停止使用副作用编程,在该程序中,您可以修改未传入,未在本地声明且未返回的自由变量。这是设计代码的不好方法。您不会从调用代码中看到足够的整体上下文,也没有在其他地方定义这些变量来对如何完成操作提出具体建议。
  2. 确定其中一个请求存在错误时,您的错误处理策略是什么,并实施该策略和适当的处理。