Асинхронный вызов нескольких API с использованием NodeJS независимо от результата каждого - PullRequest
2 голосов
/ 31 марта 2019

Я пытаюсь вызвать несколько конечных точек, используя NodeJS, и это дает результат, но проблема в том, что он дает результат после того, как все запросы получили 200 или какой-то правильный HTTP-ответ.То, что я хотел сделать, это получить все результаты, независимо от других API.Например, если я звоню 3 конечных точки, а именно.A, B, C. Если конечная точка B задерживает ответ из-за проблем с сервером, мой код не должен ждать, пока B завершит запрос и отправит ответ других завершенных запросов.

Я использую Async Promise, но он не выдает желаемый результат.Он печатает весь результат, когда самый медленный запрос API будет выполнен.

const request = require('request');

var requestAsync = function(url) {
    return new Promise((resolve, reject) => {
        var req = request(url, (err, response, body) => {
            if (err) return reject(err, response, body);
            resolve(JSON.parse(body));
        });
    });
};

const urls = [
    'https://jsonplaceholder.typicode.com/posts',
    'https://jsonplaceholder.typicode.com/albums',
    'https://jsonplaceholder.typicode.com/users',
    'http://localhost/local/node/1.php',
];


var getParallel = async function() {
    //transform requests into Promises, await all
    try {
        var data = await Promise.all(urls.map(requestAsync));
    } catch (err) {
        console.error(err);
    }
    console.log(data);
}

getParallel();

Ответы [ 3 ]

0 голосов
/ 31 марта 2019

Я не думаю, что await (или Promise.all) - это хорошо для того, чего вы пытаетесь достичь, если (к счастью) вы не ожидаете call () в качестве последнего вызова, вам придется дождитесь разрешения await (или все обещания будут разрешены или отклонены).

Скажем, у вас есть giveSome(), который выполняет некоторую асинхронную работу и возвращает Promise. Скажем, у вас есть задачи A и B. A завершается через 5 с, а B завершается через 1 с. Теперь вы делаете

// called in parallel
// both a and b are promise pending
var a = giveSome() // task A
var b = giveSome() // task B

// do something with data in async function
console.log(await a) // this is resolved only after 5s
console.log(await b) // this is already resolved after 1s but waits for the await above

Вместо этого, если вы делаете:

a.then(val => console.log(val)) // outputs val after 5s
b.then(val => console.log(val)) // outputs val after 1s

Так что в вашем случае вы могли бы:

var data = urls.map(requestAsync);

for (let i = 0; i < data.length; i++) {
  data[i]
    .then(val => console.log(val) // do something)
    // burden is you need to handle errors individually
    .catch(e => console.error(e))
}
0 голосов
/ 21 апреля 2019

Допустим, вы хотите вызывать метод x после каждого ответа. Вместо выполнения Promise.all по запросу вы можете создать еще одно Обещание для выполнения вашей работы. Оберните каждый запрос в отдельный Promise, который будет выполнять вашу работу, а затем используйте другой Promise.all, просто чтобы проверить, выполнено ли выполнение для всех. Вот пример кода -

let promises = [];

urls.forEach(url => {
  promise.push(requestAsync(url)
    .then(x)  // Replace `x`
    .catch(console.error)  // Silently dropping error
  )
})

Promise.all(promises)
  .then((results) => {
     console.log("All Executed", {results});  // Result will be response from `x` method
  })
  .catch(console.error); // If method `x` throws an error, it will go to this catch
0 голосов
/ 31 марта 2019

Используйте Promise.race, чтобы гарантировать, что возвращенное Обещание будет разрешено (или отклонено) не позднее, чем через определенный промежуток времени.Например, нижеприведенное гарантирует, что Promise.all будет либо разрешен, либо отклонен через 3000 мсек:

var requestAsync = function(url) {
    return Promise.race([
        new Promise(resolve => setTimeout(resolve, 3000, 'too slow')),
        new Promise((resolve, reject) => {
            var req = request(url, (err, response, body) => {
                if (err) return reject(err, response, body);
                resolve(JSON.parse(body));
            });
        })
    ]);
};

Если вы хотите отклонить, если какой-либо занимает слишком много времени, просто введите reject в setTimeout вместо resolve (где reject - второй параметр обратного вызова new Promise).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...