如何组织递归promises调用

时间:2015-06-29 03:40:39

标签: javascript node.js facebook-graph-api promise

我正在使用Facebook图形API,它通常会返回一个未知错误'消息,如果我在几秒钟之后重试帖子,我会发现它没有问题。

此代码将调用postAsync,在收到成功响应后,它将使用新的Promise解决该问题,否则它将递增尝试计数器并再次调用该函数。

function guaranteedPost(endpointId, wallPost, attempts){
  attempts = attempts || 0
  ++attempts
  return graph.postAsync(endpointId + '/feed', wallPost).then(function(response){
    return new Promise.resolve(response)
  }).catch(function(error){
    setTimeout(function(){    
      console.log(attempts)
      console.log(error)
      if(attempts == 2){
        return Promise.reject('Too many attempts')
      }
      else{
        return guaranteedPost(endpointId, wallPost, attempts)
      }
    }, 5000)

  });
}

guaranteedPost(endpointId, wallPost, 0).then(function(value){
  console.log(value)
})
.catch(function(error){
  console.log(error)
})

我希望能够使用这样的代码,我将其称为guaranteePost,并将响应或单个“太多”尝试登录到控制台。错误信息。但是,目前我收到的是我的输出:

undefined
Unhandled rejection Error: Too many attempts

因此,第一个调用返回undefined,第二个调用没有错误处理,就会爆炸。

另外,我想在更大的函数的上下文中使用它,它可以访问前面定义的变量,因此我不想将错误和成功处理转移到它们自己的函数中。

我无法帮助,但觉得我非常接近,但这是在一两次完整的重构之后,我仍然无法确定它。我该如何正确设计?

1 个答案:

答案 0 :(得分:1)

将超时逻辑拆分为实际的承诺,然后返回。通过执行setTimeout之类的操作,您可以捕获错误并且不返回任何内容,然后排队新请求,无需捕获其失败。承诺都是关于链接的。

function delay(ms){
  return new Promise(function(resolve){
    setTimeout(resolve, ms);
  });
}

function guaranteedPost(endpointId, wallPost, attempts){
  attempts = attempts || 0
  ++attempts
  return graph.postAsync(endpointId + '/feed', wallPost).then(function(response){
    return new Promise.resolve(response)
  }).catch(function(error){

    // Return a promise that waits a little bit, then tries again.
    return delay(5000).then(function(){    
      console.log(attempts)
      console.log(error)
      if(attempts == 2){
        return Promise.reject('Too many attempts')
      }
      else{
        return guaranteedPost(endpointId, wallPost, attempts)
      }
    })

  });
}

我还会简化这段代码:

function delay(ms){
  return new Promise(function(resolve){
    setTimeout(resolve, ms);
  });
}


function guaranteedPost(endpointId, wallPost, attempts){
  return graph.postAsync(endpointId + '/feed', wallPost)
    .catch(function(error){
      if (attempts === 2) throw new Error('Too many attempts');

      // Return a promise that waits a little bit, then tries again.
      return delay(5000).then(function(){   
         return guaranteedPost(endpointId, wallPost, (attempts | 0) + 1);
      })
    });
}