2014-10-21 27 views
7

Obietnice są moje preferowany sposób zarządzania moje asynchronicznego kodu w JavaScript. Funkcja memoize (memoizee on npm) jest biblioteką JavaScript umożliwiającą łatwe buforowanie & z wyprzedzeniem przy pobieraniu wyników funkcji.buforowanie i pre-ściągam wygasające obietnic w JavaScript

Idealnie chcę połączyć to, co najlepsze, i mieć możliwość "wygaśnięcia" obietnicy i otrzymania nowego wyniku Obietnicy (gdy pamięć podręczna zostanie dotknięta i bliska wygasaniu). Memoize może to zrobić, ale nie jest zbudowany z myślą o obietnicach.

(rozumiem, że obietnice mają wbudowany „forever-cache”, jak jest ich natura, ale zawsze jest zbyt długi dla mojej aplikacji)

Moja najlepsza próba to zrobić do tej pory jest w następujący sposób (node.js przykład stosując bluebird, memoize i underscore):

var memoize = require('memoizee') 
    , Promise = require('bluebird') 
    , _ = require('underscore') 
    ; 

// returns a memoized Promise-generating function 
function memoizePromiser(funcReturningPromise, options) { 
    var opts = _.defaults(options || {}, {async: true}); 

    return Promise.promisify(memoize(function(){ 
     var args = _.initial(arguments); 
     var cb = _.last(arguments); 
     funcReturningPromise.apply(this, args).nodeify(cb); 
    }, opts)); 
}; 

funkcja ta pozwoli mi memoize funkcję transmisji asynchronicznej (z węzłem-jak wywołania zwrotne) powrocie obietnicę, jednocześnie zapewniając cały cache-wygaśnięcie (+ więcej) funkcjonalności oferowanej przez librę Memoize ry.

Jednak takie podejście wydaje się brudny i inżynierii do mnie. Myślę sobie - z pewnością jest to dość powszechny problem, który ktoś inny stworzył bardziej eleganckim rozwiązaniem?

Jest to najlepsze podejście do tego, co mam zrobić? Czy istnieje inna biblioteka, taka jak memoize, która została zaprojektowana specjalnie dla obietnic? Czy istnieje prostsze rozwiązanie, które przegapiłem?

Wszelkie wskazówki będą mile widziane.

+1

Czy możesz wyjaśnić, co dokładnie jest nie tak z 'memoize (funcReturningPromise, options)'? Może nie rozumiem, że istnieje specjalne zachowanie dotyczące wygasania itp. Z funkcjami asynchronicznymi, czy tak jest? – Bergi

+0

Eureka! Dziękuję za wskazanie tego. Byłem pochłonięty ideą, że odkąd miałem do czynienia z kodem asynchronicznym, musiałem skorzystać z asynchronicznej funkcjonalności memoize (włączając w to niechlujny callback podobny do węzła) - ale ja nie; Obietnica jest zwracana synchronicznie. – Mikuso

+0

Postaram się odpowiedzieć :-) – Bergi

Odpowiedz

1

Ta funkcja pozwoli mi zapamiętać funkcję asynchroniczną (z callbackami podobnymi do węzłów) zwracającą obietnicę. Jednak to podejście wydaje mi się nieporządane i zbyt skomplikowane.

Tak - już masz funkcję zwracającą obietnicę, nie ma powodu, aby powracać do węzłów.

Czy istnieje prostsze rozwiązanie, które przegapiłem?

Funkcja zwracająca obietnicę jest po prostu funkcją, która zwraca pewną wartość - wartość, która może być buforowana przez funkcję memoize. Po prostu wykonaj:

memoize(funcReturningPromise, options) 
+0

Co stanie się, jeśli nie dojdzie do funkcji funcReturningPromise? Czy buforujesz awarię? –

+0

@PhilC: Tak, w takim przypadku odrzucona obietnica zostanie zapisana w pamięci podręcznej. Sądzę jednak, że tak się spodziewano, celem memoizacji jest zapobieganie wielokrotnym żądaniom. Jeśli tego nie chcesz, nadal możesz przechwytywać odrzucenia lub wyczyścić pamięć podręczną pamięci. – Bergi

+0

Rozumiem. Patrzyłem na to, aby przechowywać dobre wartości tylko dlatego, że mówisz, że muszę złapać odrzucenia i upewnić się, że nie wejdą do pamięci podręcznej- dzięki –

0

zrozumieć obietnic poprawnie - obietnica jest proxy dla wartości - raz jest on ustawiony nigdy się nie zmieni.

Jedynym sposobem obejścia tego problemu jest nie zwrócenie obietnicy za każdym razem - za każdym razem będziesz musiał zwrócić inną obietnicę (jak na przykład Twój przykład). Najprostszym rozwiązaniem byłoby użycie memoize z obiecującymi funkcjami powracającymi (i buforowanie wartości obietnicy).

Jeśli mamy function foo(){ zwracającą obietnicy. To całkiem dobrze, że po prostu sama funkcja, a następnie użyć wszystkich narzędzi, które zapewnia biblioteka.

Uwaga: promisify jest kosztowne i powoduje bardzo szybką funkcję - naprawdę nie chce nazwać przy starcie. Możesz po prostu wrócić new Promise w swoim kodzie.