Как я могу назвать 3 запроса асинхронными? - PullRequest
2 голосов
/ 24 июня 2019

Я должен сделать функциональность, чтобы проверить, работают ли 3 API. Таким образом, пользователь нажимает кнопку «Тестировать API» и возвращает статус каждого API (статус: 200, 500, 404 и т. Д.). Если API возвращает ошибку, я должен показать стек ошибок. Пример экрана:

API       Status      Detail
url1.com   200          -
url2.com   200          -
url3.com   500     internal server error

У меня вопрос: как я могу вызвать 3 запроса параллельно и вернуть асинхронный результат, я имею в виду, как я могу обновить экран статуса запроса API, не дожидаясь результата всех запросов

Я основывался на этом Как мне вызвать три запроса по порядку? , но он возвращает результат синхронно.

******* РЕДАКТИРОВАТЬ *****

Это мой текущий код

app.get('/testDependencies', function (req, res, next) {    

    let objTestsResul = {}        
    var urls = ['url1', 'url2', 'url3'];
    let index = 0
    while(urls.length > 0) {
      let url = urls.shift();
      objTestsResult[index++] = testURL(url)

   }

    res.send(objTestsResult)
});

Эта функция одинакова для каждого URL:

function testURL(URL){

   fetch(URL, {
        method: 'GET'      
    })
        .then(res => {
            res.json()            
        })
        .then(json => {
            console.log(json)
            return json      
         })
        .catch(error => {            
            return error
          })
}

Ответы [ 3 ]

3 голосов
/ 24 июня 2019

Promises ( mdn ), кажется, то, что вы ищете. По сути, они являются более читаемой версией обратных вызовов, которые позволяют выполнять код, когда происходит что-то еще, вместо того, чтобы ждать, пока произойдет этот триггер, прежде чем возобновить выполнение.

let endpoint1 = () => new Promise(resolve => setTimeout(() => resolve('200'), 1000));
  let endpoint2 = () => new Promise(resolve => setTimeout(() => resolve('201'), 2000));
  let endpoint3 = () => new Promise(resolve => setTimeout(() => resolve('500'), 1500));

  document.getElementById('test').addEventListener('click', () => {
    document.getElementById('status').textContent = 'test running...';
    Promise.all([
      endpoint1().then(a => document.getElementById('result1').textContent = a),
      endpoint2().then(a => document.getElementById('result2').textContent = a),
      endpoint3().then(a => document.getElementById('result3').textContent = a),
    ]).then(() => document.getElementById('status').textContent = 'test complete');
  });
<button id="test">test</button>
<div>status: <span id="status">not running</span></div>
<div>endpoint 1: <span id="result1"></span></div>
<div>endpoint 2: <span id="result2"></span></div>
<div>endpoint 3: <span id="result3"></span></div>
1 голос
/ 24 июня 2019

Экспресс не может отправить несколько ответов.Вам придется завершить все вызовы или использовать WebSockets для потоковой передачи данных.

function testURL(URL) {
  return new Promise((resolve, reject) => {
    if (URL === 'url2') {
      reject(new Error('Internal Server Error'));
      return;
    }
    resolve({ status: 200 });
  });
}

const main = async () => {
  const urls = ['url1', 'url2', 'url3'];

  // return resolved and rejected Promises because if one fails in Promise.all
  // the function will throw and we won't have any access to any resolved Promises.
  const results = await Promise.all(urls
    .map(url => testURL(url).then(response => response).catch(error => error)));

  // every error have a stack property, Set the status to whatever you want
  // based on the error and store the stack and the message
  const objTestsResul = results.reduce((result, cur, i) => {
    result[urls[i]] = cur.stack
      ? { status: 500, message: cur.message, stack: cur.stack }
      : cur;
    return result;
  }, {});

  console.log(objTestsResul);
};

main();
1 голос
/ 24 июня 2019

Это на самом деле довольно просто, если вы можете использовать Bluebird :

const { Promise } = require('bluebird');

app.get('/testDependencies', function (req, res, next) {    
  Promise.map(['url1', 'url2', 'url3'], url => testURL(url)).then(results => {
     res.send(results);
  });
});

Вам просто нужно убедиться, что функция вашего обещания действительно возвращает обещание:

function testURL(URL) {
  let start_time = new Date().getTime();   

  return fetch(URL, {
    method: 'GET'      
  }).then(res => {
    res.json()            
  }).then(json => {
    console.log(json)
    return json      
  }).catch(error => {            
    return error
  })
}

Обещания не могут быть связаны зависимостями, если вы явно не вернете их из функции, которая задействована в цепочке.

Если вы можете использовать async и await, я бы также порекомендовал сделатьэто также может значительно упростить сложный код.

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