Les promesses ont un statut, elles commencent comme en suspens et peuvent se régler pour:
- remplie, ce qui signifie que le calcul s'est terminé avec succès.
- rejeté, ce qui signifie que le calcul a échoué.
Les fonctions de retour de promesse ne devraient jamais être lancées , elles devraient plutôt renvoyer les rejets. Le fait de quitter une fonction de retour de promesse vous obligera à utiliser à la fois a } catch {
et a .catch
. Les personnes utilisant des API promises ne s'attendent pas à ce que des promesses soient lancées. Si vous n'êtes pas sûr du fonctionnement des API asynchrones dans JS, veuillez d'abord lire cette réponse .
1. Charge DOM ou autre événement ponctuel:
Donc, créer des promesses signifie généralement spécifier quand ils s'installent - cela signifie quand ils passent à la phase remplie ou rejetée pour indiquer que les données sont disponibles (et accessibles avec .then
).
Avec des implémentations de promesses modernes qui prennent en charge le Promise
constructeur comme les promesses natives d'ES6:
function load() {
return new Promise(function(resolve, reject) {
window.onload = resolve;
});
}
Vous utiliseriez alors la promesse résultante comme ceci:
load().then(function() {
// Do things after onload
});
Avec les bibliothèques qui prennent en charge différé (utilisons $ q pour cet exemple ici, mais nous utiliserons également jQuery plus tard):
function load() {
var d = $q.defer();
window.onload = function() { d.resolve(); };
return d.promise;
}
Ou avec une API comme jQuery, accrocher un événement qui se produit une fois:
function done() {
var d = $.Deferred();
$("#myObject").once("click",function() {
d.resolve();
});
return d.promise();
}
2. Rappel simple:
Ces API sont plutôt courantes car bon… les rappels sont courants dans JS. Regardons le cas commun d'avoir onSuccess
et onFail
:
function getUserData(userId, onLoad, onFail) { …
Avec des implémentations de promesses modernes qui prennent en charge le Promise
constructeur comme les promesses natives d'ES6:
function getUserDataAsync(userId) {
return new Promise(function(resolve, reject) {
getUserData(userId, resolve, reject);
});
}
Avec les bibliothèques qui prennent en charge différé (utilisons jQuery pour cet exemple ici, mais nous avons également utilisé $ q ci-dessus):
function getUserDataAsync(userId) {
var d = $.Deferred();
getUserData(userId, function(res){ d.resolve(res); }, function(err){ d.reject(err); });
return d.promise();
}
jQuery propose également un $.Deferred(fn)
formulaire, qui a l'avantage de nous permettre d'écrire une expression qui émule de très près le new Promise(fn)
formulaire, comme suit:
function getUserDataAsync(userId) {
return $.Deferred(function(dfrd) {
getUserData(userId, dfrd.resolve, dfrd.reject);
}).promise();
}
Remarque: Ici, nous exploitons le fait qu'un jQuery différé resolve
et les reject
méthodes sont "détachables"; c'est à dire. ils sont liés à l' instance d'un jQuery.Deferred (). Toutes les bibliothèques n'offrent pas cette fonctionnalité.
3. Rappel de style de nœud ("nodeback"):
Les rappels de style nœud (nœuds) ont un format particulier où les rappels sont toujours le dernier argument et son premier paramètre est une erreur. Promettons d'abord un manuellement:
getStuff("dataParam", function(err, data) { …
À:
function getStuffAsync(param) {
return new Promise(function(resolve, reject) {
getStuff(param, function(err, data) {
if (err !== null) reject(err);
else resolve(data);
});
});
}
Avec les reports, vous pouvez effectuer les opérations suivantes (utilisons Q pour cet exemple, bien que Q supporte désormais la nouvelle syntaxe que vous devriez préférer ):
function getStuffAsync(param) {
var d = Q.defer();
getStuff(param, function(err, data) {
if (err !== null) d.reject(err);
else d.resolve(data);
});
return d.promise;
}
En général, vous ne devez pas trop promettre des choses manuellement, la plupart des bibliothèques de promesses conçues avec Node à l'esprit ainsi que les promesses natives dans Node 8+ ont une méthode intégrée pour promettre les dos de nœud. Par exemple
var getStuffAsync = Promise.promisify(getStuff); // Bluebird
var getStuffAsync = Q.denodeify(getStuff); // Q
var getStuffAsync = util.promisify(getStuff); // Native promises, node only
4. Toute une bibliothèque avec des rappels de style nœud:
Il n'y a pas de règle d'or ici, vous les promettez un par un. Cependant, certaines implémentations de promesse vous permettent de le faire en bloc, par exemple dans Bluebird, la conversion d'une API nodeback en API de promesse est aussi simple que:
Promise.promisifyAll(API);
Ou avec des promesses natives dans Node :
const { promisify } = require('util');
const promiseAPI = Object.entries(API).map(([key, v]) => ({key, fn: promisify(v)}))
.reduce((o, p) => Object.assign(o, {[p.key]: p.fn}), {});
Remarques:
- Bien sûr, lorsque vous êtes dans un
.then
gestionnaire, vous n'avez pas besoin de promettre des choses. Le renvoi d'une promesse d'un .then
gestionnaire résoudra ou rejettera la valeur de cette promesse. Lancer d'un .then
gestionnaire est également une bonne pratique et rejettera la promesse - c'est la fameuse promesse de sécurité du lancer.
- Dans un
onload
cas réel , vous devez utiliser addEventListener
plutôt que onX
.