2016-04-01 5 views
5

Opracowałem bibliotekę klienta, która udostępnia metodę o nazwie iterator(). Ta metoda zwraca instancję Promise utworzoną przy użyciu biblioteki require('promise'), którą uzupełnia obiekt iteratora.Nierekurencyjna metoda iteracji nad iteratorem obietnicy

Cel ten zawiera metodę zwaną next() która zwraca Promise, co dokonywane jest z kompleksem przedmiotu, jak to: {done: [true|false], key: _, value: _}

Chociaż iterator() może wstępnego ładowania kilka elementów, next() musi zwracać obiecujące w przypadku skutkuje połączenie zdalne.

Teraz powiedzmy, że użytkownik chce iterować po wszystkich elementach, dopóki obietnica zwrócona przez next() nie zwróci obiektu zawierającego done: true.

udało mi się to osiągnąć stosując następujący sposób rekurencyjny (I pierwotnie znaleźć takie rozwiązanie w tej 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; 
    }); 

}); 

Chodzi o to, byłoby to możliwe, przy użyciu require('promise') bibliotekę, budować rozwiązanie nierekurencyjne? Powodem, dla którego interesuje mnie metoda nierekursywna, jest unikanie wysadzania w powietrze, jeśli liczba wpisów do iteracji jest zbyt duża.

Cheers, Galder

+0

Wygląda na to, że szukasz generatora lub obserwujesz. – ssube

+0

możesz użyć innego rozwiązania, które wykrywa rekursję dla ciebie, ale nadal będzie to rozwiązanie rekursywne. – smnbbrv

+0

Galder, prawdopodobnie chcesz przeczytać sekcję zatytułowaną "Kolekcja Kerfuffle" [tutaj] (http://taoofcode.net/promise- anti-patterns /) –

Odpowiedz

2

Powodem Jestem zainteresowany metody non-rekurencyjne jest uniknięcie wysadzenie jeśli liczba zgłoszeń do iteracyjnego jest zbyt duży

nie bój. Asynchroniczna "rekursja" (czasami określana jako pseudo-recursion) nie rozwija stosu wywołań, przypomina rekursję ogonową. Nigdy nie otrzymasz wyjątku stackoverflow.

Jeśli biblioteka obietnic jest rozsądnie wdrożona, nie powinno to nawet powiększać pamięci - patrz: Building a promise chain recursively in javascript - memory considerations w celu uzyskania szczegółowych informacji.

1

bez nowych składni lub biblioteki - na ogół nie.

Cóż, jeśli używasz babel, można użyć ES2018 (: P) asynchronicznej iteracji:

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

read more about it here

W przeciwnym razie, można skorzystać z generatorów asynchronicznych ES2016/Oczekujcie składnia:

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

Albo z dostępnych dzisiaj ES2015 generatora składni i pompy poprzez bluebird:

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

Wielkie dzięki za te rozwiązania, ale żaden z nich nie działa dla mnie. Używam ES2015 i wymagam Node.js 0.10 (bluebird Promise.coroutine wymaga Node.js 0.12). –

+0

@ GalderZamarreño w jaki sposób używasz ES2015, jeśli używasz NodeJS 0.10? –

+1

Ponadto odpowiedź pozostaje bez rekursji lub metody pomocniczej, która sama rekurencja - jest to niemożliwe przed ES2015 –