2014-08-28 2 views
1

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

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

Используемый асинхронный API возвращает Q.

Как я могу отменить оригинальный вызов изящно, гарантируя, что даже если система вернется со значением для первого вызова, часть обещания не будет вызываться с этим значением (но что она в конечном итоге вызывается, когда вторая асинхронный вызов завершен)?

+3

Почему бы не отказаться? –

+0

Я не вижу отклонения от прототипа обещания. – Ben

+0

потребитель обещания не может его изменить - только отложенные могут быть изменены. –

ответ

1

В тот же день у меня был такой случай (node.js), где я либо делал веб-сайт, либо запрос db. У меня был объект тайм-аута, который, я думаю, был отменен (прошу, не помню деталей) и обещал обе им. Поэтому, если веб-страница вернулась в первую очередь, я отменил таймаут и вернул html. И если тайм-аут произошел первым, я обновил поле «timedout» в каком-то JSON до «да», так что, если бы веб-вызов когда-либо возвращался, он знал бы, что умереть. Это было немного сногсшибательно, потому что с этими обещаниями я мог войти в функцию один раз и фактически вернуться дважды!

Надежда, что помогает

-Tom

0

Отсутствуют некоторые отмены API, каждый асинхронной вызов будет выполняться до завершения, но если все, что вы ищете, отменяя .then() функции, то это выполнимо , Самый прямой способ является счетчик:

var counter = 0; 

function onClick() { 
    counter++; 
    doAsyncCall().then(function(result) { 
    if (!--counter) { 
     myFunc(result); 
    } 
    }); 
} 

Но вы просили изящным, так что, возможно, более многоразовые конструкция будет что-то вроде этого:

var idle; 

function onClick(){ 
    idle = Overtake(idle, doAsyncCall()); 
    idle.then(myFunc).then(myOtherFunc); 
} 

, которые могут быть реализованы следующим образом:

function Overtaker(prior, callp) { 
    if (prior) { 
    prior.cancel(); 
    } 
    var p; 
    p = new Promise(function(resolve, reject) { 
    callp.then(function(value) { return p && resolve(value); }, 
       function(reason) { return p && reject(reason); }); 
    }); 
    this.cancel = function() { p = null; } 
    this.then = function(onFulfilled, onRejected) { 
    return p.then(onFulfilled, onRejected); 
    } 
} 

function Overtake(prior, p) { 
    return new Overtaker(prior, p); 
} 

Я использую обещания ES6, но обещания Q кажутся похожими, поэтому, надеюсь, это работает и там.