асинхронный внутри цикла for nodejs - PullRequest
0 голосов
/ 10 октября 2018

Я пытаюсь получить доступ к 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 голосов
/ 10 октября 2018

Используйте библиотеку запроса-обещания, которая предоставляет обещанные версии библиотеки запросов.Затем вы можете использовать async / await в вашем цикле for для сериализации ваших операций:

Более новый ответ, соответствующий отредактированному коду в вопросе 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;
}

В вашем коде неясно, где options, pepTimecards, pepResponse переменные объявлены.Вероятно, они должны быть здесь объявлены как локальные переменные или переданы в функцию и / или возвращены из вашей функции.


Сводка изменений:

  1. Добавьте async в объявление метода, чтобы мы могли использовать await.
  2. Загрузить библиотеку запроса-обещания в rp переменную
  3. Добавить options.json = true в библиотеку let запроса-обещанияпроанализируйте для нас результат JSON автоматически
  4. Измените rp(), чтобы просто использовать структуру параметров (добавьте URL к этому)
  5. Добавьте try / catch, чтобы перехватить любые ошибки из журнала awaitих, а затем перебросьте, чтобы pageno() вернул обещание, которое отклоняется при возникновении ошибки (при желании можно настроить поведение при возникновении ошибки)
  6. Добавить возвращаемое значение, чтобы в значимом разрешенном значении былообещание (вы не должны использовать программирование побочных эффектов, как сейчас (изменение переменных, которые не были переданы, объявлены локально или возвращены).

Что вам еще нужно исправить:

  1. Прекратите использовать программирование побочных эффектов, когда вы изменяете свободные переменные, которые не передаются, не объявляются локально и не возвращаются.Это плохой способ разработки кода.Вы не показываете достаточно общего контекста из вызывающего кода или того, где определены эти другие переменные, чтобы дать конкретную рекомендацию о том, как это должно быть сделано.
  2. Решите, какова ваша стратегия обработки ошибок, если есть ошибка на одном из них.запросов и реализовать эту стратегию и надлежащую обработку.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...