массив из рекурсивного запроса на выборку не возвращается должным образом

1

Я пытаюсь изучить привязку к курсору с помощью 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);
  • 2
    fetch async ...
  • 1
    final - очень-очень-очень плохое имя для переменной.
Показать ещё 2 комментария
Теги:
arrays
fetch-api
slack-api

1 ответ

1
Лучший ответ

Это потому, что код внутри функции then выполняется позже (привет async ждет :).

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!'));
  • 0
    спасибо за подробный ответ и объяснение (все еще перечитываю, чтобы я мог понять. Мне пришлось добавить аргумент "ts" в selectChannel и заставить функцию execute возвращать finalData, чтобы он возвращал кого-то за пределами selectChannel. Теперь он возвращает 100, когда я надеюсь, что он вернется 204. Вы ответили на мой вопрос, но теперь мне нужно выяснить, почему он принимает данные только для первого вызова извлечения и не действует рекурсивно. Спасибо большое !!
  • 1
    Я настроил код, который вы предоставили, и получил мою цель, используя этот jsfiddle.net/gp6f8Lyv

Ещё вопросы

Сообщество Overcoder
Наверх
Меню