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!

Foi útil?

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 
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top