Dans le code suivant:
var p1 = new Promise(function (resolve, reject) {
throw 'test1';
});
var p2 = new Promise(function (resolve, reject) {
reject('test2');
});
p1.catch(function (err) {
console.log(err); // test1
});
p2.catch(function (err) {
console.log(err); // test2
});
Existe-t-il une différence entre utiliser reject
(dans p2
) à partir de l'API Promise
et générer une erreur (dans p1
) en utilisant throw
C'est exactement pareil?
Si c'est la même chose, pourquoi avons-nous besoin d'un rappel reject
alors?
Existe-t-il une différence entre utiliser
reject
(dansp2
) à partir de l'APIPromise
et générer une erreur (dansp1
) en utilisantthrow
Oui, vous ne pouvez pas utiliser throw
de manière asynchrone, alors que reject
est un rappel. Par exemple, un délai d'attente:
new Promise(_, reject) {
setTimeout(reject, 1000);
});
C'est exactement pareil?
Non, du moins pas lorsqu'un autre code suit votre déclaration. throw
termine immédiatement la fonction de résolution, tandis que l'appel de reject
continue son exécution normalement - après avoir "marqué" la promesse comme rejetée.
En outre, les moteurs peuvent fournir des informations de débogage des exceptions différentes si vous throw
objets d'erreur.
Pour votre exemple spécifique, vous avez raison de dire que p1
et p2
sont impossibles à distinguer de l'extérieur.
Non, il n'y en a pas, les deux sont complètement identiques. La seule différence et la raison pour laquelle nous avons besoin de reject
est lorsque vous devez rejeter de manière asynchrone. Par exemple, si vous convertissez une API basée sur le rappel, il peut être nécessaire de signaler une erreur asynchrone.
var p = new Promise(function(resolve, reject){
someCallbackApi(function(err, data){
if(err) reject(err); // CAN'T THROW HERE, non promise context, async.
else resolve(data);
});
});
Je sais que c'est un peu tard, mais je ne pense pas que l'une ou l'autre de ces réponses réponde complètement aux questions que j'avais quand j'ai trouvé ceci. Voici un exemple plus complet à jouer.
var p1 = new Promise(function (resolve, reject) {
throw 'test 1.1'; //This actually happens
console.log('test 1.1.1'); //This never happens
reject('test 1.2'); //This never happens because throwing an error already rejected the promise
console.log('test 1.3'); //This never happens
});
var p2 = new Promise(function (resolve, reject) {
reject('test 2.1'); //This actually happens
console.log('test 2.1.1'); //This happens BEFORE the Promise is rejected because reject() is a callback
throw 'test 2.2'; //This error is caught and ignored by the Promise
console.log('test 2.3'); //This never happens
});
var p3 = new Promise(function (resolve, reject) {
setTimeout(function() { reject('test 3.1');}, 1000); //This never happens because throwing an error already rejected the promise
throw('test 3.2'); //This actually happens
console.log('test 3.3'); //This never happens
});
var p4 = new Promise(function (resolve, reject) {
throw('test 4.1'); //This actually happens
setTimeout(function() { reject('test 4.2');}, 1000); //This never happens because throwing an error already rejected the promise
console.log('test 4.3'); //This never happens
});
var p5 = new Promise(function (resolve, reject) {
setTimeout(function() { throw('test 5.1');}, 1000); //This throws an Uncaught Error Exception
reject('test 5.2'); //This actually happens
console.log('test 5.3'); //This happens BEFORE the Promise is rejected because reject() is a callback
});
var p6 = new Promise(function (resolve, reject) {
reject('test 6.1'); //This actually happens
setTimeout(function() { throw('test 6.2');}, 1000); //This throws an Uncaught Error Exception
console.log('test 6.3'); //This happens BEFORE the Promise is rejected because reject() is a callback
});
p1.then(function (resolve) {
console.log(resolve, "resolved")
}, function (reject) {
console.log(reject, "rejected")
}).catch(function (err) {
console.log(err, "caught"); // test1
});
p2.then(function (resolve) {
console.log(resolve, "resolved")
}, function (reject) {
console.log(reject, "rejected")
}).catch(function (err) {
console.log(err, "caught"); // test2
});
p3.then(function (resolve) {
console.log(resolve, "resolved")
}, function (reject) {
console.log(reject, "rejected")
}).catch(function (err) {
console.log(err, "caught"); // test3
});
p4.then(function (resolve) {
console.log(resolve, "resolved")
}, function (reject) {
console.log(reject, "rejected")
}).catch(function (err) {
console.log(err, "caught"); // test4
});
p5.then(function (resolve) {
console.log(resolve, "resolved")
}, function (reject) {
console.log(reject, "rejected")
}).catch(function (err) {
console.log(err, "caught"); // test5
});
p6.then(function (resolve) {
console.log(resolve, "resolved")
}, function (reject) {
console.log(reject, "rejected")
}).catch(function (err) {
console.log(err, "caught"); // test6
});
Une observation très intéressante est que si vous utilisez throw
, il sera d'abord géré par le gestionnaire reject
, puis par le gestionnaire error
si aucun gestionnaire de rejet n'est en place.
Avec bloc de gestion des rejets
var allowed = false;
var p1 = new Promise(
function(resolve, reject) {
if (allowed)
resolve('Success');
else
// reject('Not allowed');
throw new Error('I threw an error')
})
p1.then(function(fulfilled) {
console.log('Inside resolve handler, resolved value: ' + fulfilled);
}, function(rejected) {
console.log('Inside reject handler, rejected value: ' + rejected);
}).catch(function(error) {
console.log('Inside error handler, error value: ' + error);
})
Sans bloc de gestion des rejets
var allowed = false;
var p1 = new Promise(
function(resolve, reject) {
if (allowed)
resolve('Success');
else
// reject('Not allowed');
throw new Error('I threw an error')
})
p1.then(function(fulfilled) {
console.log('Inside resolve handler, resolved value: ' + fulfilled);
}).catch(function(error) {
console.log('Inside error handler, error value: ' + error);
})
De plus, le bloc catch pourra capturer toute erreur renvoyée dans le gestionnaire resolve
.
var allowed = true;
var p1 = new Promise(
function(resolve, reject) {
if (allowed)
resolve('Success');
else
// reject('Not allowed');
throw new Error('I threw an error')
})
p1.then(function(fulfilled) {
console.log('Inside resolve handler, resolved value: ' + fulfilled);
throw new Error('Error created inside resolve handler block');
}).catch(function(error) {
console.log('Inside error handler, error value: ' + error);
})
Il semble préférable d'utiliser throw
, sauf si vous ne le pouvez pas si vous exécutez une tâche asynchrone, vous devrez transmettre le rappel reject
à la fonction async. Mais il y a un moyen de contourner le problème, c'est de promettre votre fonction asynchrone. Plus d'informations sur https://stackoverflow.com/a/33446005