【问题标题】:How do I call 3 requests async?如何异步调用 3 个请求?
【发布时间】:2019-06-25 02:34:37
【问题描述】:

我必须做一个功能来测试 3 个 API 是否正在运行。 因此,用户将单击 Test APIs 按钮,它将返回每个 API 的状态(状态:200、500、404 等)。如果 API 返回错误,我应该显示错误堆栈。 屏幕示例:

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

我的问题是,如何并行调用 3 个请求并返回异步结果,我的意思是如何在不等待所有请求结果的情况下更新 API 请求状态屏幕

我是基于那个How do I call three requests in order?,但是它会同步返回结果。

*******编辑*****

这是我当前的代码

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
          })
}

【问题讨论】:

  • 你检查Promise.all了吗?
  • 你将不得不展示我们应该修复的代码。
  • 请发布您目前所拥有的 :)
  • 好的。到目前为止,我将使用代码更新问题
  • 在这种情况下,只需分别发出所有请求,并让每个请求在屏幕上更新自己的元素(或将内容附加到单个现有元素)。从字面上看,只有 3 个独立的独立请求就可以满足您的需求。没有什么聪明的要求。如果这是客户端 Ajax,那就是(默认运行异步)。还是您在谈论服务器端代码?

标签: javascript node.js promise


【解决方案1】:

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>

【讨论】:

    【解决方案2】:

    如果您可以使用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);
      });
    });
    

    您只需要确保您的 Promise 函数实际返回一个 Promise:

    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
      })
    }
    

    除非您从参与链接的函数中显式返回它们,否则 Promise 不能被依赖链接。

    如果您能够使用 asyncawait,我还建议您这样做,因为这样可以大大简化原本复杂的代码。

    【讨论】:

      【解决方案3】:

      Express 无法发送多个回复。您必须完成所有通话或使用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();

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-01-24
        • 2015-05-03
        • 2023-02-06
        • 2020-04-14
        • 2014-04-10
        • 2023-04-06
        • 1970-01-01
        相关资源
        最近更新 更多