Выполнение динамического количества запросов с последовательными параметрами - PullRequest
0 голосов
/ 03 февраля 2019

Я создаю приложение, в котором мне нужно делать последовательно пронумерованные запросы, начиная с указанного номера.Это мой первый проект node.js, поэтому я учусь по ходу дела, но я застрял в этой конкретной проблеме.

Мне нужно передать идентификатор, чтобы я мог сослаться на него позже.По сути, мне нужно использовать данные из первого запроса, чтобы сделать второй запрос к другому API.Большая часть данных, поступивших на второй запрос, будет получена из ответа на первый запрос, но идентификатор не нужен, поэтому мне нужно как-то передать его.

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

var id = process.argv[2];
var numIterations = process.argv[3] || 5;
var apiRequests = [];

for (var i = 0; i < numIterations; i++) {
    var requestDetails = {
        uri: 'https://www.example.com/id=' + id,
        json: false
    };

    apiRequests.push(
        rp(requestDetails).then(
            function (data) {
                return {
                    id: id,
                    html: data 
                };
            }
        )
    );

    id++;
}

Promise.all(apiRequests)
    .then((results) => {
        for (var i = 0; i < results.length; i++) {
            console.log(results[i].id); continue;
        }
    }).catch(err => console.log(err));

Если id = 1 и numIterations = 5 дляНапример, тогда я ожидал бы увидеть: 1 2 3 4 5

Но вместо этого я вижу: 5 5 5 5 5

Я понимаю, почему это происходит из-за того, как работает запрос-обещание, но яЯ не уверен, как лучше это решить.

1 Ответ

0 голосов
/ 03 февраля 2019

Результат object вашего apiRequest ({ id: id, html: data };) будет создан асинхронно после выполнения обещания.в этот момент переменной id присвоено последнее значение.поэтому все создаваемые результирующие объекты будут иметь одинаковое значение.

Чтобы решить эту проблему, вы должны сохранять ссылку на свой идентификатор на каждом шаге for.Поэтому определите array, чтобы он сохранял сгенерированные идентификаторы, и вставьте в него каждый идентификатор, и, поскольку он имеет тот же порядок, что и apiRequests, вы можете получить к ним доступ по индексу results.

var apiRequests = [];
var ids = [];
// ...
apiRequests.push(/* ... */);
ids.push(id);
// ...
console.log(ids[i]);

Альтернативное решение будет использовать let вместо var, если это возможно.Как хорошо описано здесь :

var ограничено до ближайшего функционального блока, а let - до ближайшего окружающего блока.

ЕслиВы определяете переменную let внутри for, уникальный экземпляр будет создаваться на каждом шаге, и, как указано в вашем объекте, он будет сохраняться до выхода из области действия функции.Таким образом, реализация будет выглядеть примерно так:

for (var i = 0; i < numIterations; i++) {
    let finalId = id; // add this line
    var requestDetails = {
        uri: 'https://www.example.com/id=' + id,
        json: false
    };

    apiRequests.push(
        rp(requestDetails).then(
            function (data) {
                return {
                    id: finalId, // update this line
                    html: data 
                };
            }
        )
    );

    id++;
}

В качестве совета попробуйте использовать let и const вместо var

...