【问题标题】:Recursive asynchronous api calls递归异步 api 调用
【发布时间】:2017-10-28 01:35:58
【问题描述】:

我正在做一个需要我使用 twitter api 的项目。试图返回给定用户的所有关注者。问题是让所有用户 bc twitter 将关注者分成最多 200 个块。

我在网上看到了一个解决方案,他们递归地调用回调,但是我在继续之前尝试使用 Promise 来取回所有数据时遇到了困难。目前它等待第一页返回,但不知道如何让它等待所有的承诺返回。 有人可以给我任何提示/提示吗?是否有办法迭代地做到这一点?

let cursor = -1;
let promise = new Promise((resolve,reject)=>{
      twitter.followers({cursor},function callback(data, error){
       if(error)
           reject(false)
      cursor = data.next_cursor;
      if(cursor!=0){
           new Promise((resolve,reject)=>{
                twitter.followers({cursor},callback)
           })
           resolve(true);
      }
})
})
promise.then({
    //do stuff
})

【问题讨论】:

    标签: javascript node.js asynchronous recursion


    【解决方案1】:

    你已经接近了,但你的方法只需要一些调整:

    • 出现错误时,除了reject()之外别做任何事情
    • 不要创建新的嵌套承诺,而是使用当前承诺:延迟对 resolve()(或 reject())的任何调用,直到调用下一个回调。
    • 只有resolve()光标到达0时。
    • 最后的then 需要一个回调参数,而不是一个对象字面量。

    这是调整后的代码(使用twitter.followers 的虚拟实现使其工作):

    // Mock implementation, for the snippet to work:
    var twitter = {
        followers: function (obj, callback) {
            setTimeout(function () {
                callback({
                    next_cursor: (obj.cursor + 5) % 6
                }, 0);
            }, 100);
        }
    }
    
    let cursor = -1;
    let promise = new Promise((resolve,reject)=>{
        twitter.followers({cursor}, function callback(data, error){
            if (error) {
                reject(false)
                return; // Don't continue after error
            }
            cursor = data.next_cursor;
            console.log(cursor);
            if (cursor != 0){
                // Don't create a new promise, just delay to resolve
                twitter.followers({cursor}, callback)
                return; // don't resolve now
            }
            resolve(true);
        })
    })
    promise.then(function () { // You need a callback function here
        console.log('all done');
    })

    【讨论】:

      【解决方案2】:

      首先,创建一个函数来获取一些数据并返回一个 Promise。我不确定你的确切会是什么样子,但可能是这样的:

      function getFollowers(args) {
          return new Promise((resolve, reject) => {
              twitter.followers(args, function(data, error) {
                  if (error) {
                      reject(error);
                  } else {
                      resolve(data);
                  }
              });
          });
      }
      

      然后,您可以在 .then() 处理程序中递归调用该函数,并从 .then() 处理程序返回新的承诺,以自动将其链接到前一个承诺。

      function getAllFollowers(user) {
          return getFollowers(...).then(data => {
               if (data.next_cursor) {
                   return getFollowers(...).then(data => {
                       // collect data here
                   });
               } else {
                   return accumulated_data;
               }
          });
      }
      
      getAllFollowers(...).then(data => {
          // got all data here
      }).catch(err => {
          // error here
      });
      

      请注意,这部分是伪代码,因为我没有遵循您尝试实现的确切逻辑或您正在使用的 API。但是,一般的想法是,您可以从 .then() 处理程序中递归地返回一个新的 Promise,然后它会自动将它链接到前一个 Promise 上。

      如果您想从所有调用中累积一些数据,那么您还需要在递归调用的 .then() 处理程序中执行此操作,以便累积您想要的总数据(您不会显示任何关于什么您尝试收集的结果类型,因此此代码不会显示)。

      【讨论】:

      • 你太棒了!这正是我正在寻找的逻辑,但由于某种原因,我自己无法想出它。
      • 其实我还是有点迷茫。递归步骤将如何工作?从伪代码看来,似乎只调用了两次 getFollowers。
      • 等等,我想你的意思是放 getAllFollowers 而不是 getFollowers 对吗?
      • @Leon - 这取决于你想要做什么。我不明白您希望递归逻辑如何工作。你来决定。
      猜你喜欢
      • 2018-01-30
      • 2021-05-12
      • 2016-09-21
      • 1970-01-01
      • 2014-12-18
      • 2015-08-04
      • 2015-08-27
      • 2014-05-21
      • 2016-04-28
      相关资源
      最近更新 更多