2016-04-01 4 views
5

Я разработал клиентскую библиотеку, которая предоставляет метод под названием iterator(). Этот метод возвращает экземпляр Promise, созданный с использованием библиотеки require('promise'), которая завершается объектом итератора.Нерекурсивный метод для повторения итератора Promise

Этот объект содержит метод, называемый next(), который возвращает Promise, который завершается со сложным объектом, как это: {done: [true|false], key: _, value: _}

Хотя iterator() может упреждающего некоторые элементы, next() потребности вернуть обещание в случае, если это приводит к удаленный вызов.

Теперь, скажем, пользователь хочет перебрать все элементы до тех пор, пока обещание, возвращаемое next(), не возвращает объект, содержащий done: true.

мне удалось добиться этого с помощью следующего рекурсивного метода (изначально я нашел это решение в этом answer):

var iterate = client.iterator(); 

iterateTeams.then(function(it) { 

    function loop(promise, fn) { 
    // Simple recursive loop over iterator's next() call 
    return promise.then(fn).then(function (entry) { 
     return !entry.done ? loop(it.next(), fn) : entry; 
    }); 
    } 

    return loop(it.next(), function (entry) { 
    console.log('entry is: ' + entry); 
    return entry; 
    }); 

}); 

Вопрос заключается в том, будет ли это возможно, используя require('promise') библиотеку, чтобы построить нерекурсивное решение? Причина, по которой меня интересует нерекурсивный метод, заключается в том, чтобы избежать взрыва, если количество записей для итерации слишком велико.

Приветствия, Galder

+0

Похоже, что вы ищете генератор или наблюдаемый. – ssube

+0

вы можете использовать другое решение, которое _hides_ рекурсия для вас, но это все равно будет рекурсивным решением – smnbbrv

+0

Galder, вы, вероятно, захотите прочитать раздел «The Collection Kerfuffle» [здесь] (http://taoofcode.net/promise- anti-patterns /) –

ответ

2

Причина Я заинтересован в нерекурсивна метода является то, чтобы избежать раздутия, если число записей перебирать не слишком большой

Не бойся. Асинхронная «рекурсия» (иногда дублируется pseudo-recursion) не увеличивает стек вызовов, это очень похоже на рекурсию хвоста. Вы никогда не получите исключение stackoverflow.

И если библиотека обещаний реализована разумно, это не должно даже увеличивать память - см. Building a promise chain recursively in javascript - memory considerations для деталей.

1

Без нового синтаксиса или библиотеки - вообще нет.

Ну, если вы используете столпотворение, вы можете использовать ES2018 (: P) асинхронной итерации:

for await (const team of iterateTeams) { 
    // do something with team 
} 

read more about it here

В противном случае, вы можете использовать генераторы с ES2016 асинхронной/Await синтаксис:

for(var it = iterateTeams(); !done; ({done, value}) = await it.next()) { 
    // work with value 
}  

Или с имеющимися сегодня ES2015 синтаксисом генератора и насоса через bluebird:

// inside a Promise.corutine 
for(var it = iterateTeams(); !done; ({done, value}) = yield it.next()) { 
    // work with value 
}  
+0

Большое спасибо за эти решения, но никто из них не работает для меня. Я использую ES2015 и требую Node.js 0.10 (bluebird Promise.coroutine требует Node.js 0.12). –

+0

@ GalderZamarreño, как вы используете ES2015, если используете NodeJS 0.10? –

+1

Кроме того, ответ по-прежнему стоит, без рекурсии или вспомогательного метода, который сам рекурсирует - это невозможно до ES2015. –

Смежные вопросы