2016-05-31 2 views
2

Я пришел к осознанию того, что, поскольку обещания в ECMAScript 6 допускают синхронное кодирование асинхронных функций, для каждого обезборенного фрагмента кода существует синхронное следствие. Например:Обещающая версия цикла «while»?

var data = processData(JSON.parse(readFile(getFileName()))); 

То же самое, как:

var data = getFileName() 
    .then(readFile) 
    .then(JSON.parse) 
    .then(processData); 

Теперь для моего нынешнего потребительного случае, если я хочу, чтобы написать код для извлечения данных из массивного публичного API. API разбивается на страницы, так и в чисто синхронном мире, я бы написать что-то вроде следующего:

var data = []; 
var offset = 0; 
var total = 10000; // For example - not actually how this would work 
while(offset < total) { 
    data.concat(getDataFromAPI(offset)); 
    offset = data.length; 
} 

Теперь мой вопрос, как бы я это делать с обещаниями? Я мог бы написать что-то вроде:

var data = []; 
var offset = 0; 
var total = 10000; 
getDataFromAPI(offset) 
    .then(function(newData){ 
     data.concat(newData); 
     return getDataFromAPI(data.length); 
    }); 

Но в этот момент я вынужден просто цепь бесконечных .then с - нет зацикливания логики. Я чувствую, что что-то должно быть возможно с помощью рекурсии, но я понятия не имею, как это сделать.

Я использую BluebirdJS как свою библиотеку обещаний, поэтому у меня есть доступ ко всем их вспомогательным методам.

+0

А как насчет рекурсивной самоназывающей анонимной функции (в конечном итоге в сочетании с обещаниями)? вот только пример: https://jsfiddle.net/f5ud8ytx/. Замените тайм-аут на свой собственный вызов api и используйте. Then обещания, возвращенного из вызова api, чтобы снова вызвать функцию до тех пор, пока конец не достигнет 0 (текущий - выполняется до конца выше 0) – briosheje

+0

вы можете легко сделать это с помощью ' асинхронному each' – r3wt

ответ

6

Я чувствую, что что-то должно быть возможно с помощью рекурсии

Ровно. Вы можете назвать обратный вызов, чтобы вы могли ссылаться на него снова. Пока условие не выполняется, верните обещание от обратного вызова. В противном случае верните окончательный результат:

getDataFromAPI(offset) 
    .then(function next(newData){ 
    data.concat(newData); 
    var newOffset = data.length; 
    return newOffset < total ? getDataFromAPI(newOffset).then(next) : data; 
    }) 
    .then(function(data) { 
    console.log(data); // final result 
    }); 
Смежные вопросы