sintaxe para Jquery.deferred , fazendo promessa de retorno de função síncrona
-
11-12-2019 - |
Pergunta
Uma pergunta rápida sobre como usar Jquery.deferred para fazer uma função síncrona lenta retornar uma promessa.O que fiz até agora foi o seguinte:
function sayIt(ms) {
setTimeout( function() { console.log('what I say'); }, ms);
}
function doIt() {
return $.Deferred( function() { sayIt(2000); }).promise();
}
doIt().then( function() { console.log('ah'); });
o sayIt(2000) sempre passa, mas a função encadeada após o 'então' nunca é acionada.
Se eu fizer isso:
doIt().then( console.log('ah'));
o 'ah' surge imediatamente, e então o 'o que eu digo' 2.000 ms depois - o que eu quero é, claro, o oposto - que depois de dois segundos eu receba 'o que eu digo' e então 'ah' logo depois.
Qualquer sugestão será apreciada!
Solução
Para fazer algo de forma síncrona, mas ainda usar uma promessa, faça:
function slowPromise() {
var def = $.Deferred();
// do something slow and synchronous
...
// resolve the deferred with the result of the slow process
def.resolve(res);
// and return the deferred
return def.promise();
}
O efeito é que você ainda recebe uma promessa, mas essa promessa já está resolvida, então qualquer .then()
que é posteriormente registrado nele prossegue imediatamente.
A vantagem desse padrão é que se você substituir posteriormente o código síncrono por algo assíncrono, a função ainda terá a mesma interface externa.
Outras dicas
Se você deseja executar uma função após o tempo limite expirar, você precisa chamar resolve()
no Deferred
objeto de dentro da função de expiração de tempo limite:
function sayIt(ms) {
var d = $.Deferred();
setTimeout(function() {
console.log('what I say');
d.resolve()
}, ms);
return d;
}
Desta forma você restringe a resolução do Deferred
contestar a expiração do tempo limite.
Para alcançar o que acredito ser sua intenção:
function doIt() {
return sayIt(2000).promise()
}
O .promise()
a chamada é opcional.Restringe apenas a interface disponível para chamadores:ao devolver um Promise
em vez do original Deferred
objeto, o chamador só pode reagir aos eventos, mas não acioná-los.Referência: http://api.jquery.com/deferred.promise/.
Eventualmente, sua chamada original:
doIt().then( function() { console.log('ah'); });
Produzirá:
// 2 seconds delay
what I say
ah