Maison > Article > interface Web > Javascript : Guide complet de la promesse
Promise est une nouvelle solution de programmation asynchrone. ES6 l'a intégré au standard du langage, unifiant son utilisation et fournissant nativement l'objet Promise.
Son introduction a grandement amélioré la situation difficile de la programmation asynchrone, évitant ainsi l'enfer des rappels. C'est plus raisonnable et plus puissant que les solutions traditionnelles comme les fonctions de rappel et les événements.
Une promesse, en termes simples, est un constructeur qui contient le résultat d'un événement qui se terminera dans le futur (généralement une opération asynchrone). Syntaxiquement, une promesse est un objet à partir duquel des messages d'opération asynchrone peuvent être récupérés. Promise fournit une API unifiée, permettant de gérer diverses opérations asynchrones de la même manière.
Il peut résoudre efficacement le problème de l'enfer des rappels dans ES5 (en évitant les fonctions de rappel profondément imbriquées).
Il suit une norme unifiée, avec une syntaxe concise, une forte lisibilité et maintenabilité.
L'objet Promise fournit une API simple, ce qui rend la gestion des tâches asynchrones plus pratique et plus flexible.
Lors de l'utilisation d'une Promesse, nous pouvons la classer en trois états :
en attente : En attente. C'est l'état initial, où la Promesse n'est ni remplie ni rejetée.
réalisé : Réalisé/Résolu/Réussi. Lorsque solve() est exécuté, la promesse entre immédiatement dans cet état, indiquant qu'elle a été résolue et que la tâche a été terminée avec succès.
rejeté : Rejeté/Échec. Lorsque rejet() est exécuté, la promesse entre immédiatement dans cet état, indiquant qu'elle a été rejetée et que la tâche a échoué.
Lorsque new Promise() est exécuté, l'état de l'objet de promesse est initialisé à ending, qui est son état initial. Le contenu entre parenthèses de la nouvelle ligne Promise() est exécuté de manière synchrone. Entre parenthèses, vous pouvez définir une fonction pour une tâche asynchrone, qui a deux paramètres : résoudre et rejeter. Par exemple :
// Create a new promise const promise = new Promise((resolve, reject) => { //promise's state is pending as soon as entering the function console.log('Synchronous Operations'); //Begin to execute asynchronous operations if (Success) { console.log('success'); // If successful, execute resolve() to switch the promise's state to Fulfilled resolve(Success); } else { // If failed, excecute reject() to pass the error and switch the state to Rejected reject(Failure); } }); console.log('LukeW'); //Execute promise's then():to manage success and failure situations promise.then( successValue => { // Process promise's fulfilled state console.log(successValue, 'successfully callback'); // The successMsg here is the Success in resolve(Success) }, errorMsg => { //Process promise's rejected state console.log(errorMsg, 'rejected'); // The errorMsg here is the Failure in reject(Failure) } );
Le constructeur Promise prend comme paramètre une fonction, qui a deux arguments : résoudre et rejeter.
const promise = new Promise((resolve, reject) => { // ... some code if (/* Success */){ resolve(value); } else { reject(error); } });
La valeur de retour de Promise.resolve(value) est également un objet de promesse, qui peut être enchaîné avec un appel .then. Le code est le suivant :
Promise.resolve(11).then(function(value){ console.log(value); // print 11 });
Dans le code solve(11), cela entraînera la transition de l'objet promis vers l'état résolu, en passant l'argument 11 à la fonction onFulfilled spécifiée dans le .then suivant. Un objet de promesse peut être créé à l'aide de la nouvelle syntaxe Promise ou en utilisant Promise.resolve(value).
function testPromise(ready) { return new Promise(function(resolve,reject){ if(ready) { resolve("hello world"); }else { reject("No thanks"); } }); }; testPromise(true).then(function(msg){ console.log(msg); },function(error){ console.log(error); });
La signification du code ci-dessus est de passer un argument à la méthode testPromise, qui renvoie un objet de promesse. Si l'argument est vrai, la méthode solve() de l'objet promis est appelée, et le paramètre qui lui est transmis est ensuite transmis à la première fonction du .then suivant, ce qui donne la sortie "hello world". Si l'argument est faux, la méthode rejet() de l'objet de promesse est appelée, ce qui déclenche la deuxième fonction du .then, conduisant à la sortie "Non merci."
La méthode then peut accepter deux fonctions de rappel comme paramètres. La première fonction de rappel est appelée lorsque l'état de l'objet Promise passe à résolu, et la deuxième fonction de rappel est appelée lorsque l'état de l'objet Promise passe à rejeté. Le deuxième paramètre est facultatif et peut être omis.
La méthode then renvoie une nouvelle instance Promise (pas l'instance Promise d'origine). Par conséquent, une syntaxe chaînée peut être utilisée, où une autre méthode then est appelée après la première.
Lorsque vous devez écrire des événements asynchrones en séquence, exigeant qu'ils soient exécutés en série, vous pouvez les écrire comme ceci :
let promise = new Promise((resolve,reject)=>{ ajax('first').success(function(res){ resolve(res); }) }) promise.then(res=>{ return new Promise((resovle,reject)=>{ ajax('second').success(function(res){ resolve(res) }) }) }).then(res=>{ return new Promise((resovle,reject)=>{ ajax('second').success(function(res){ resolve(res) }) }) }).then(res=>{ })
En plus de la méthode then, un objet Promise possède également une méthode catch. Cette méthode est équivalente au deuxième paramètre de la méthode then, pointant vers la fonction de rappel pour le rejet. Cependant, la méthode catch a une fonction supplémentaire : si une erreur se produit ou si une exception est levée lors de l'exécution de la fonction de rappel de résolution, elle n'arrêtera pas l'exécution. Au lieu de cela, il entrera dans la méthode catch.
p.then((data) => { console.log('resolved',data); },(err) => { console.log('rejected',err); } ); p.then((data) => { console.log('resolved',data); }).catch((err) => { console.log('rejected',err); });
The all method can be used to complete parallel tasks. It takes an array as an argument, where each item in the array is a Promise object. When all the Promises in the array have reached the resolved state, the state of the all method will also become resolved. However, if even one of the Promises changes to rejected, the state of the all method will become rejected.
let promise1 = new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve(1); },2000) }); let promise2 = new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve(2); },1000) }); let promise3 = new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve(3); },3000) }); Promise.all([promise1,promise2,promise3]).then(res=>{ console.log(res); //result:[1,2,3] })
When the all method is called and successfully resolves, the result passed to the callback function is also an array. This array stores the values from each Promise object when their respective resolve functions were executed, in the order they were passed to the all method.
The race method, like all, accepts an array where each item is a Promise. However, unlike all, when the first Promise in the array completes, race immediately returns the value of that Promise. If the first Promise's state becomes resolved, the race method's state will also become resolved; conversely, if the first Promise becomes rejected, the race method's state will become rejected.
let promise1 = new Promise((resolve,reject)=>{ setTimeout(()=>{ reject(1); },2000) }); let promise2 = new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve(2); },1000) }); let promise3 = new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve(3); },3000) }); Promise.race([promise1,promise2,promise3]).then(res=>{ console.log(res); //result:2 },rej=>{ console.log(rej)}; )
So, what is the practical use of the race method? When you want to do something, but if it takes too long, you want to stop it; this method can be used to solve that problem:
Promise.race([promise1,timeOutPromise(5000)]).then(res=>{})
The finally method is used to specify an operation that will be executed regardless of the final state of the Promise object. This method was introduced in the ES2018 standard.
promise .then(result => {···}) .catch(error => {···}) .finally(() => {···});
In the code above, regardless of the final state of the promise, after the then or catch callbacks have been executed, the callback function specified by the finally method will be executed.
In work, you often encounter a requirement like this: for example, after sending an A request using AJAX, you need to pass the obtained data to a B request if the first request is successful; you would need to write the code as follows:
let fs = require('fs') fs.readFile('./a.txt','utf8',function(err,data){ fs.readFile(data,'utf8',function(err,data){ fs.readFile(data,'utf8',function(err,data){ console.log(data) }) }) })
The above code has the following drawbacks:
The latter request depends on the success of the previous request, where the data needs to be passed down, leading to multiple nested AJAX requests, making the code less intuitive.
Even if the two requests don't need to pass parameters between them, the latter request still needs to wait for the success of the former before executing the next step. In this case, you also need to write the code as shown above, which makes the code less intuitive.
After the introduction of Promises, the code becomes like this:
let fs = require('fs') function read(url){ return new Promise((resolve,reject)=>{ fs.readFile(url,'utf8',function(error,data){ error && reject(error) resolve(data) }) }) } read('./a.txt').then(data=>{ return read(data) }).then(data=>{ return read(data) }).then(data=>{ console.log(data) })
This way, the code becomes much more concise, solving the problem of callback hell.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!