2015-10-19 10 views
9

Piszę kod do wykonania pollingu dla zasobu co N ms, który powinien upłynąć po M sekundach. Chcę, żeby cała ta obietnica opierała się na Bluebirdie tak bardzo, jak to możliwe. Rozwiązanie, do którego do tej pory doszedłem, wykorzystuje interwał węzła, anulowane obietnice Bluebirda i funkcję limitu czasu bluebirda.Co to jest dobry wzorzec dla "interwału z przekroczeniem czasu" przy użyciu Promises

Zastanawiam się, czy istnieje lepszy sposób na ograniczenie interwałów z bluebirdem i obietnicami w ogóle? Głównie upewniając się, że interwał zatrzymuje się w punkcie i nigdy nie trwa w nieskończoność.

var Promise = require('bluebird'); 

function poll() { 
    var interval; 

    return new Promise(function(resolve, reject) { 
    // This interval never resolves. Actual implementation could resolve. 
    interval = setInterval(function() { 
     console.log('Polling...') 
    }, 1000).unref(); 
    }) 
    .cancellable() 
    .catch(function(e) { 
     console.log('poll error:', e.name); 
     clearInterval(interval); 
     // Bubble up error 
     throw e; 
    }); 
} 

function pollOrTimeout() { 
    return poll() 
    .then(function() { 
     return Promise.resolve('finished'); 
    }) 
    .timeout(5000) 
    .catch(Promise.TimeoutError, function(e) { 
     return Promise.resolve('timed out'); 
    }) 
    .catch(function(e) { 
     console.log('Got some other error'); 
     throw e; 
    }); 
} 

return pollOrTimeout() 
    .then(function(result) { 
    console.log('Result:', result); 
    }); 

wyjściowa:

Polling... 
Polling... 
Polling... 
Polling... 
poll error: TimeoutError 
Result: timed out 

Odpowiedz

5

chciałbym zrobić coś takiego -

function poll() { 
    return Promise.resolve().then(function() { 
    console.log('Polling...'); 
    if (conditionA) { 
     return Promise.resolve(); 
    } else if (conditionB) { 
     return Promise.reject("poll error"); 
    } else { 
     return Promise.delay(1000).then(poll); 
    } 
    }) 
    .cancellable() 
} 

być także świadomi Promise constructor anti-pattern

+1

Nice. Jak zakończyłbyś interwał? Wygląda na jedyne wyjście, jeśli rzucisz błąd. Wiem, że konstruktor Promise to anty-wzór, ale w tym przypadku wydawało się, że pasuje (to samo z wydarzeniami + obietnicami, ale to inny temat). – Chris911

+0

Ok teraz rozumiem twoje pytanie. Sprawdź moją edycję. – vinayr

+0

Tak, to działa. Dziękuję i przyjąłem odpowiedź. – Chris911

1

Rene Wooller sprawia naprawdę dobry punkt:

Ostrzeżenie: niestety, rekurencja w javascript jak to będzie ostatecznie nasycić stos wywołań i prowadzić z wyjątkami pamięci

Nawet jeśli to nie wyjątek, to jest marnowana przestrzeń, a ryzyko związane z wyjątkiem może zachęcić do nadmiernego opóźnienia w odpytywaniu.

myślę, że jest na tyle ważne, aby wolą setInterval:

var myPromise = new Promise((resolve, reject) => { 
    var id = window.setInterval(() => { 
     try { 
      if (conditionA) { 
       window.clearInterval(id); 
       resolve("conditionA"); 
      } else if (conditionB) { 
       throw new Error("conditionB!"); 
      } 
     } catch(e) { 
      window.clearInterval(id); 
      reject(e); 
     } 
    }, 1000); 
}); 

Istnieje kilka pakietów KMP że adres ten wymóg, którego lubię promise-waitfor najlepszy. Ma 38 linii i wykonuje swoją pracę.

var myPromise = waitFor(() => { 
    if(conditionA) return true; 
    if(conditionB) throw new Error("conditionB!"); 
    return false; 
}); 
+0

Czy możesz mi wyjaśnić, jak by to osiągnąć, gdyby (warunek A) była obietnicą? Nie mogę nigdy uciec przed łańcuchem obietnic, aby zwrócić proste "true" lub "false" w waitFor(). – NZHammer

+1

Możesz dodać osobne pytanie, gdy "conditionA" jest obietnicą. Prawdopodobnie rozwiązanie obejmuje 'Promise.race'. –

+0

Przeczytałem, że jeśli twoja ankieta będzie trwała dłużej niż twój setinverval, zbuduje kolejkę. Następnie, gdy się zakończy, musi przetworzyć kolejkę. I lepiej jest użyć funkcji setTimeout i rekursji, aby uruchomić inny setTimeout. – TamusJRoyce

Powiązane problemy