2013-06-20 10 views
15

chcę zrobić coś jak następuje:Czy mogę złożyć synchroniczną obietnicę w bibliotece JavaScript Q?

delay(2500) 
    .then(function() { console.log("Step 1 done") }) 
    .then(delay(7500)) 
    .then(function() { console.log("Step 2 done") }); 

więc realizacja opóźnienia wykazano wiele razy:

function delay(ms) { 
    var deferred = Q.defer(); 
    setTimeout(deferred.resolve, ms); 
    return deferred.promise; 
} 

Ale jeśli uruchomię powyższe node.js uzyskać:

... delay of 2500ms 
Step 1 done 
Step 2 done 
... delay of ~7500ms 

raczej niż to, co spodziewają się zobaczyć:

... delay of 2500ms 
Step 1 done 
... delay of 7500ms 
Step 2 done 

W przykładach podanych na https://github.com/kriskowal/q/wiki/Examples-Gallery nie mogę znaleźć żadnych przykładów funkcji synchronicznych (funkcji, które zwracają wartość bez żadnych wywołań zwrotnych) powiązanych z obietnicami funkcji.

Wszelkie pomysły na łączenie w akcjach synchronicznych z asynchronicznymi obietnicami?

Próbowałem:

function synchronousPromise() { 
    var deferred = Q.defer(); 
    console.log("Synchronous function call"); 
    deferred.resolve(); 
    return deferred.promise; 
} 

delay(2500) 
    .then(function(){synchronousPromise()}) 
    .then(function(){delay(7500)}) 
    .then(function(){synchronousPromise()}); 

A to wyjścia:

... delay of 2500ms 
Time now is 2013-06-20 
Time now is 2013-06-20 
... delay of 7500ms 

.. nadal nie co próbuję osiągnąć.

+1

W twoim pierwszym przykładzie wypróbowałeś '.then (function() {return delay (7500);})' zamiast '.then (delay (7500))'? –

+0

@FelixKling, który działa dla pierwszego i drugiego przykładu! Złóż swoją odpowiedź, a ja ją zaakceptuję. –

+0

Możesz teraz osiągnąć to bez konieczności określenia czasu opóźnienia sprawdź mój [odpowiedź] (http://stackoverflow.com/questions/17213297/can-i-make-a-synchronous-promise-in-the-javascript-q -library/33298652 # answer-33298652). –

Odpowiedz

13

Jeśli chcesz powiązać wywołania zwrotne, musisz zwrócić nowy obiekt obietnicy z jednego z wywołań zwrotnych. W pierwszym przykładzie, piszesz

.then(delay(7500)) 

co oznacza, że ​​są przechodzącą obiektu obiecują .then, nie jest funkcją. Zgodnie z Promise/A+ proposal (który Q następuje), wszystkie niefunkcjonalne argumenty muszą zostać zignorowane. Tak w zasadzie to samo, jak gdyby po prostu napisać:

delay(2500) 
    .then(function() { console.log("Step 1 done"); }) 
    .then(function() { return delay(7500); }) 
    .then(function() { console.log("Step 2 done"); }); 

Teraz ostatni zwrotna zostanie wywołana tylko raz obietnicę:

delay(2500) 
    .then(function() { console.log("Step 1 done") }) 
    .then(function() { console.log("Step 2 done") }); 

Zamiast funkcję, która wywołuje delay i zwraca obiekt obietnica przejść obiekt zwrócony przez delay w drugim wywołaniu zwrotnym został rozwiązany.

3

Google przyniósł mi tutaj pracując przez podobny problem (ale przy użyciu Q Kris Kowal za), skończyło się z bardzo małych ramy, które pozwala wykonać następujące czynności:

var chain = [ 
    doNext(delay, 2500), 
    doNext(console.log, "Step 1 done"), 
    doNext(delay, 7500), 
    doNext(console.log, "Step 2 done") 
]; 

doInOrder(chain); 

The ram jest zaledwie 12 wierszy i prawdopodobnie może być przystosowana do innych bibliotek Obiecujemy:

var Q = require('q'); 

function doNext(fn /* , arguments */){ 
    var args = Array.prototype.splice.call(arguments, 1); 
    return function(prevRetVal){ 
    // For my needs I didn't need the results from previous fns 
    return fn.apply(null, args) 
    } 
} 

function doInOrder(doNexters, init){ 
    return doNexters.reduce(Q.when, init); 
} 
0

Jeśli pracujesz z Babel lub maszynopis można użyć ES6 Generators:

'use strict'; 

    let asyncTask =() => 
    new Promise(resolve => { 
     let delay = Math.floor(Math.random() * 1000); 

     setTimeout(function() { 
     resolve(delay); 
     }, delay); 
    }); 

    let makeMeLookSync = fn => { 
    let iterator = fn(); 
    let loop = result => { 
     !result.done && result.value.then(res => 
     loop(iterator.next(res))); 
    }; 

    loop(iterator.next()); 
    }; 

    makeMeLookSync(function*() { 
    let result = yield asyncTask(); 

    console.log(result); 
    }); 
Powiązane problemy