【问题标题】:Recursive promise for failed requests失败请求的递归承诺
【发布时间】:2017-12-26 09:00:52
【问题描述】:

我有一个 main 函数,它可以并行发出一系列 GET 请求。使用Promise.all 函数评估它们的状态。

var promises = [];

for ( var i = 0; i < list.length; i++ )
{
   promises.push( REQ( list[ i ], 0 ) );
}

var responses = await Promise.all( promises );

REQ 函数返回一个承诺。

async function REQ( url, attempts )
{
   await sleep( 5000 * attempts ); // Uses a promise with setTimeout

   return new Promise( ( resolve, reject ) => {
      request( url, function ( error, response, body )
      {
         if ( error )
         {
            if ( attempts > ATTEMPT_THRESHOLD )
               reject( error );
            else
               return REQ( url, ++attempts );
         }
         else
         {
            if ( typeof body === 'undefined' || body.length === 0 )
            {
               if ( attempts > ATTEMPT_THRESHOLD )
                  reject( error );
               else
                  return REQ( url, ++attempts );
            }
            else
               resolve( { response, body } );
         }
      });
   });
};

我创建REQ 函数async 的原因是,如果请求失败,它会重新尝试,但如果它正在查询的服务器拥塞,重新尝试会延迟一点。

问题似乎是在 Node 控制台中,程序在重新尝试时挂起,这样如果 REQ 失败,它的重新尝试不会返回到原来的 REQ 并返回承诺。

【问题讨论】:

  • 尝试用while循环实现同样的逻辑

标签: node.js ecmascript-6 promise


【解决方案1】:

它的重新尝试不会返回原始REQ并返回promise。

当然不是。在new Promise 构造函数中,您需要resolve 承诺而不是return 它。

如果您在尽可能低的级别上做出承诺会更好,即只包装request 和仅 request,而不是任何重试业务逻辑:

function requestAsync(url) {
  return new Promise((resolve, reject) => {
    request(url, (error, response, body) => {
      if (error) reject(error);
      else resolve({response, body});
    });
  });
}

那么你就可以照常使用await和return了。

async function REQ(url, attempts) {
  try {
    const res = await requestAsync(url);
    if (typeof res.body == "undefined" || res.body.length == 0)
      throw new Error("no response"); // or throw undefined to get the original behaviour
    return res;
  } catch(error) {
    if (attempts > ATTEMPT_THRESHOLD)
      throw error;
    ++attempts;
    await sleep(5000 * attempts);
    return REQ(url, attempts);
  }
}

【讨论】:

    猜你喜欢
    • 2017-11-01
    • 2014-05-06
    • 2013-12-02
    • 2014-02-04
    • 1970-01-01
    • 1970-01-01
    • 2018-05-29
    • 1970-01-01
    • 2018-09-25
    相关资源
    最近更新 更多