Je souhaite exécuter la même action, que ma promesse soit résolue avec succès ou non. Je ne veux pas lier la même fonction aux deux arguments de .then
. N'y a-t-il pas un .always
comme jQuery? Si non, comment puis-je y parvenir?
N'y a-t-il pas un
.always
comme jQuery?
Non, il n'y a pas (encore) . Bien qu'il y ait une proposition active , alors peut-être ES2018.
Si non, comment puis-je y parvenir?
Vous pouvez implémenter vous-même la méthode finally
comme ceci:
Promise.prototype.finally = function(cb) {
const res = () => this
const fin = () => Promise.resolve(cb()).then(res)
return this.then(fin, fin);
};
ou plus largement, en passant des informations de résolution au rappel:
Promise.prototype.finally = function(cb) {
const res = () => this
return this.then(value =>
Promise.resolve(cb({state:"fulfilled", value})).then(res)
, reason =>
Promise.resolve(cb({state:"rejected", reason})).then(res)
);
};
Les deux assurent que la résolution d'origine est maintenue (lorsqu'il n'y a pas d'exception dans le rappel) et que des promesses sont attendues.
Si vous ne pouvez pas/ne pouvez pas mettre à jour le prototype, voici comment procéder:
executeMyPromise()
.then(function(res){ return {res: res}; })
.catch(function(err){ return {err: err}; })
.then(function(data) {
// do finally stuff
if (data.err) {
throw data.err;
}
return data.res;
}).catch(function(err) {
// handle error
});
Voici mon implémentation de .finally ().
Promise.prototype.finally = function(cb) {
return this.then(v=>Promise.resolve(cb(v)),
v=>Promise.reject(cb(v)));
};
Je l'ai testé:
(new Promise((resolve,reject)=>{resolve(5);})).finally(x=>console.log(x)); //5
(new Promise((resolve,reject)=>{reject(6);})).finally(x=>console.log(x)); //6
(new Promise((resolve,reject)=>{reject(7);}))
.then(x=>x,y=>y)
.catch(x=>{throw "error";})
.finally(x=>{console.log(x); throw "error"; return x;}) // 7
.then(x=>console.log(x),y=>console.log('e')); //e
// Uncaught (in promise) undefined
Nous avons également maintenant accès à Promise.prototype.finally()
. C'est une fonction qui peut être ajoutée à la chaîne de promesse en tant que dernier élément pour effectuer un nettoyage. cela fonctionne de la manière suivante par rapport à Promise.then
et Promise.catch
:
Promise.then
only est appelé lorsque la promesse est résolue (si vous ne la mettez que comme fonction de rappel du premier argument)Promise.catch
only est appelé lorsque la promesse est rejetéePromise.finally
always est appelé quand une promesse est remplie, donc les deux quand la promesse est rejetée ou résolue. let Prom = new Promise((res, rej) => {
let random = Math.random();
if (random > 0.5) {
res(1);
} else {
rej('Error occured')
}
});
Prom.then((val) => {
console.log(val);
return val * 10;
}).catch((err) => {
console.log(err);
}).finally(() => {
console.log('finally executed');
})
Dans l'exemple ci-dessus, nous pouvons observer que finally
est toujours exécuté, que la promesse soit résolue ou rejetée. Non pas que finally
devrait idéalement toujours être à la fin de la chaîne de promesse pour effectuer un nettoyage qui devrait être exécuté quel que soit le résultat de Promise.
L'utilisation de finally
présente l'avantage d'éviter la duplication de code, car celle-ci est exécutée pour une promesse résolue ou rejetée. Sinon, nous devrions utiliser des hacks comme:
.then(onfullfilled, onfullfilled)
ou
.then(onfullfilled)
.catch(onfullfilled)
Notez que maintenant nous devons définir la fonction onfullfilled
en tant que fonction nommée en dehors du gestionnaire de promesses lui-même (ou passer 2 copies de fonctions anonymes qui sont encore moins élégantes). Promise.finally
résout ce problème pour nous.
Pour prolonger la réponse Bergi.
Renvoyer Promise.reject () dans le gestionnaire de captures empêchera la finnalisation de "then" à appeler.
Donc, si vous allez gérer une erreur de promesse plus de 2 fois, vous devez utiliser un passe-partout comme ceci:
return myPromise()
.then(() => ... )
.catch((error) => {
...
myFinnaly();
return Promise.reject(error);
})
.then(() => myFinnaly());
Pas besoin d'introduire de nouveaux concepts
const promise = new Promise((resolve, reject) => {
/*some code here*/
});
promise.then(() => {
/* execute success code */
}, () => {
/* execute failure code here */
}).then(() => {}, () => {}).then(() => {
/* finally code here */
});