Я пытаюсь изучить привязку к курсору с помощью 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);
Это потому, что код внутри функции 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!'));
final
- очень-очень-очень плохое имя для переменной.