Многократный вызов функции до тех пор, пока ее обещание не будет разрешено или пока не истечет установленный тайм-аут.

У меня есть функция, которая приводит к большому количеству ошибок, поэтому мне приходится вызывать ее много раз, прежде чем она, наконец, даст правильный результат. Он возвращает обещание, поэтому я создал вокруг него оболочку, которая рекурсивно продолжает вызывать его при отклонении.

Я хочу вернуть новое обещание, созданное с помощью Bluebird, но который должен быть отклонен по истечении установленного времени ожидания. И он должен постоянно вызывать эту функцию. Но перед каждым повторением я хочу проверить, не было ли оно автоматически отклонено из-за тайм-аута.

Bluebird имеет isRejected(), но, похоже, я не могу использовать его изнутри тело обещания:

var promise = new Promise(function(resolve, reject){
    var self = this;
    setTimeout(reject, TIMEOUT*1000);
    return doSomethingWrapper();
    function doSomethingWrapper(){

        if(promise.isRejected()) return;
        // Error: Cannot read property 'isRejected' of undefined

        if(self.isRejected()) return;
        // Error: self.isRejected is not a function

        return doSomething().then(resolve, doSomethingWrapper).catch(doSomethingWrapper);
    }
});

Любое другое решение?


person laggingreflex    schedule 24.08.2015    source источник
comment
Нет смысла использовать его из тела промиса, а так как doSomethingWrapper вызывается немедленно, обратный вызов setTimeout никоим образом не сработает, поэтому в любом случае нет необходимости проверять.   -  person Ry-♦    schedule 24.08.2015


Ответы (2)


Создайте обещание тайм-аута:

var timeout = Bluebird.delay(TIMEOUT * 1000).then(function () {
    return Bluebird.reject(new Error("Timed out"));
});

Создайте обещание операции:

var something = (function doSomethingWrapper() {
    if (timeout.isRejected()) {
        return;
    }

    return doSomething().catch(doSomethingWrapper);
})();

Соревнуйтесь с ними:

var promise = Bluebird.race(something, timeout);
person Ry-♦    schedule 24.08.2015

На самом деле это можно сделать проще:

Promise.try(function doSomethingWrapper(){ 
   return doSomething().catch(doSomethingWrapper); // retry
}).timeout(TIMEOUT * 1000);

Гонки не нужны :)

person Benjamin Gruenbaum    schedule 24.08.2015
comment
timeout отменяет рекурсию? Я не публиковал этот ответ, потому что не был уверен. - person Bergi; 24.08.2015