来自递归获取请求的数组未正确返回

时间:2017-09-24 18:35:50

标签: javascript arrays api slack-api fetch-api

我正在尝试使用Slack的API学习基于光标的分页。我的目标是使用channel.history方法返回所有消息的数组。

我有一个javascript递归获取函数,但我似乎无法让局部变量“final”正确返回。

记录“分页结果成功”的部分是按预期记录并返回数组,长度为204.

当在该范围之外调用“final”时,长度为0。

我已经尝试过在哪里返回变量final,但似乎无法使其正常工作。我认为这与不使用回调函数有关,但我不知道在哪里实现它。

这就是我所拥有的(删除了我的Slack令牌)。

function paginate() {
  let final = [];

  let selectChannel = function(ts) {
    fetch('https://slack.com/api/channels.history?token=MY_TOKEN&channel=C6W9FH2S0&latest=' + ts)
      .then(response => response.json())
      .then(responseData => {
        let messages = responseData.messages;
        if (!responseData.has_more) {
          final.push.apply(final, messages);
          console.log('Pagination results successfull, 204 items in the array!', final);
          return final;
        } else {
          final.push.apply(final, messages);
          selectChannel(messages[messages.length - 1].ts);
        }
        return final;
      })
      .catch(error => {
        console.log('Error fetching and parsing data', error);
      });
  }

  selectChannel(new Date());
  // Returning as 0, when I am expecting 204
  console.log("Final Output", final.length);
  return final;
}


var x = paginate();
// By extention, this is returning as 0, when I am expecting 204 as well
console.log("Output", x.length);

1 个答案:

答案 0 :(得分:1)

这是因为then函数内的代码稍后执行(hello async await:)。

fetch()返回将来执行某个点的承诺,并且可以返回此承诺并添加另一个then()方法并在其中调用console.log()

以下是按执行顺序排列的代码块,这可能会澄清:

function paginate() {  /* 2 */
  let final = [];

  let selectChannel = function(ts) { /* 4 */
    fetch('https://slack.com/api/channels.history?token=MY_TOKEN&channel=C6W9FH2S0&latest=' + ts)
      .then(response => response.json() /* 8 */)
      .then(responseData => { /* 9 */
        let messages = responseData.messages;
        if (!responseData.has_more) {
          final.push.apply(final, messages);
          console.log('Pagination results successfull, 204 items in the array!', final);
          return final;
        } else {
          final.push.apply(final, messages);
          selectChannel(messages[messages.length - 1].ts);
        }
        return final;
      })
      .catch(error => { /* 10 */
        console.log('Error fetching and parsing data', error);
      });
  }

  selectChannel(new Date()); /* 3 */
  // Returning as 0, when I am expecting 204
  console.log("Final Output", final.length); /* 5 */
  return final; /* 6 */
}


var x = paginate(); /* 1 */
// By extention, this is returning as 0, when I am expecting 204 as well
console.log("Output", x.length); /* 7 */

正如您所看到的那样,步骤7记录了x.length结果,而仅在步骤9中,此结果最终填充(最终变量在步骤/代码块9中填充)

在异步世界中,您的代码将(必须)看起来像这样:

async function selectChannel() {
    try {
        var response = await fetch('https://slack.com/api/channels.history?token=MY_TOKEN&channel=C6W9FH2S0&latest=' + ts);
        var responseData = await response.json();
        let messages = responseData.messages;
        if (!responseData.has_more) {
            final.push.apply(final, messages);
            console.log('Pagination results successfull, 204 items in the array!', final);
            return final;
        } else {
            final.push.apply(final, messages);
            await selectChannel(messages[messages.length - 1].ts);
        }
        return final;
    } catch (error) {
        console.log('Error fetching and parsing data', error);
    }
}

async function execute() {
    var finalData = await selectChannel(new Date());
    console.log("Final Output", finalData.length);
}

execute() // optionally: .then(x=> console.log('we are finished executing!'));
相关问题