syntaxe pour Jquery.deferred, faisant la promesse de retour de fonction synchrone
-
11-12-2019 - |
Question
Une petite question sur la façon d'utiliser Jquery.deferred pour qu'une fonction synchrone lente renvoie une promesse à la place.Ce que j'ai fait jusqu'à présent est ceci :
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'); });
le sayIt(2000) passe toujours mais la fonction chaînée après le « alors » ne se déclenche jamais.
Si je fais ceci :
doIt().then( console.log('ah'));
le « ah » apparaît tout de suite, puis le « ce que je dis » 2000 ms plus tard - ce que je veux, c'est bien sûr le contraire - qu'après deux secondes j'obtienne « ce que je dis » puis « ah » juste après.
Toutes suggestions appréciées!
La solution
Pour faire quelque chose de manière synchrone, tout en utilisant une promesse, faites :
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();
}
L'effet est que vous recevez toujours une promesse, mais cette promesse est déjà résolue, donc tout .then()
qui y est ensuite enregistré se déroule immédiatement.
L'avantage de ce modèle est que si vous remplacez ultérieurement le code synchrone par quelque chose d'asynchrone, la fonction a toujours la même interface externe.
Autres conseils
Si vous souhaitez exécuter une fonction après l'expiration du délai d'attente, vous devez appeler resolve()
sur le Deferred
objet à partir de la fonction d'expiration du délai d'attente :
function sayIt(ms) {
var d = $.Deferred();
setTimeout(function() {
console.log('what I say');
d.resolve()
}, ms);
return d;
}
De cette façon, vous limitez la résolution du Deferred
s'opposer à l'expiration du délai d'attente.
Pour réaliser ce que je crois être votre intention :
function doIt() {
return sayIt(2000).promise()
}
Le .promise()
l'appel est facultatif.Il restreint uniquement l'interface disponible pour les appelants :en renvoyant un Promise
au lieu de l'original Deferred
objet, l'appelant ne peut que réagir aux événements, mais pas les déclencher.Référence: http://api.jquery.com/deferred.promise/.
Finalement, votre appel initial :
doIt().then( function() { console.log('ah'); });
Affichera :
// 2 seconds delay
what I say
ah