Rumah > Artikel > hujung hadapan web > Javascript: Panduan Lengkap Janji
Promise ialah penyelesaian baharu untuk pengaturcaraan tak segerak. ES6 telah memasukkannya ke dalam standard bahasa, menyatukan penggunaannya dan menyediakan objek Promise secara asli.
Pengenalannya telah meningkatkan kesusahan pengaturcaraan tak segerak, mengelakkan panggilan balik neraka. Ia lebih munasabah dan berkuasa daripada penyelesaian tradisional seperti fungsi dan acara panggil balik.
Promise, secara ringkasnya, ialah pembina yang memegang hasil acara yang akan selesai pada masa hadapan (biasanya operasi tak segerak). Secara sintaksis, Janji ialah objek dari mana mesej operasi tak segerak boleh diambil. Promise menyediakan API bersatu, membolehkan pelbagai operasi tak segerak dikendalikan dengan cara yang sama.
Ia boleh menyelesaikan masalah neraka panggil balik dengan berkesan dalam ES5 (mengelakkan fungsi panggil balik bersarang dalam).
Ia mengikut standard bersatu, dengan sintaks yang ringkas, kebolehbacaan yang kuat dan kebolehselenggaraan.
Objek Promise menyediakan API yang ringkas, menjadikannya lebih mudah dan fleksibel untuk mengurus tugas tak segerak.
Apabila menggunakan Promise, kita boleh mengklasifikasikannya kepada tiga keadaan:
belum selesai: Belum selesai. Ini adalah keadaan awal, di mana Janji tidak ditepati atau ditolak.
dipenuhi: Dipenuhi/Diselesaikan/Berjaya. Apabila resolve() dilaksanakan, Promise serta-merta memasuki keadaan ini, menunjukkan bahawa ia telah diselesaikan dan tugas itu telah berjaya diselesaikan.
ditolak: Ditolak/Gagal. Apabila reject() dilaksanakan, Promise serta-merta memasuki keadaan ini, menunjukkan bahawa ia telah ditolak dan tugas itu telah gagal.
Apabila Promise() baharu dilaksanakan, keadaan objek promise dimulakan kepada belum selesai, iaitu keadaan awalnya. Kandungan dalam kurungan baris Promise() baharu dilaksanakan secara serentak. Dalam kurungan, anda boleh menentukan fungsi untuk tugas tak segerak, yang mempunyai dua parameter: selesaikan dan tolak. Contohnya:
// 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) } );
Pembina Promise mengambil fungsi sebagai parameternya, yang mempunyai dua hujah: selesaikan dan tolak.
const promise = new Promise((resolve, reject) => { // ... some code if (/* Success */){ resolve(value); } else { reject(error); } });
Nilai pulangan Promise.resolve(value) juga merupakan objek janji, yang boleh dirantai dengan panggilan .then. Kodnya adalah seperti berikut:
Promise.resolve(11).then(function(value){ console.log(value); // print 11 });
Dalam kod resolve(11), ia akan menyebabkan objek promise beralih kepada keadaan diselesaikan, menghantar hujah 11 kepada fungsi onFulfilled yang dinyatakan dalam .then seterusnya. Objek janji boleh dibuat menggunakan sintaks Promise baharu atau dengan menggunakan 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); });
Maksud kod di atas ialah menghantar hujah kepada kaedah testPromise, yang mengembalikan objek janji. Jika hujah itu benar, kaedah resolve() bagi objek janji dipanggil dan parameter yang dihantar kepadanya kemudian dihantar ke fungsi pertama dalam .then seterusnya, menghasilkan output "hello world." Jika hujah itu palsu, kaedah reject() bagi objek promise dipanggil, yang mencetuskan fungsi kedua dalam .then, yang membawa kepada output "Tidak, terima kasih."
Kaedah kemudian boleh menerima dua fungsi panggil balik sebagai parameter. Fungsi panggil balik pertama dipanggil apabila keadaan objek Promise berubah kepada diselesaikan, dan fungsi panggil balik kedua dipanggil apabila keadaan objek Promise berubah kepada ditolak. Parameter kedua adalah pilihan dan boleh diabaikan.
Kaedah kemudian mengembalikan contoh Promise baharu (bukan contoh Promise asal). Oleh itu, sintaks berantai boleh digunakan, di mana kaedah lain kemudian dipanggil selepas yang pertama.
Apabila anda perlu menulis acara tak segerak dalam urutan, memerlukannya untuk dilaksanakan secara bersiri, anda boleh menulisnya seperti ini:
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=>{ })
Selain kaedah kemudian, objek Promise juga mempunyai kaedah tangkapan. Kaedah ini bersamaan dengan parameter kedua kaedah kemudian, menunjuk kepada fungsi panggil balik untuk menolak. Walau bagaimanapun, kaedah tangkapan mempunyai fungsi tambahan: jika ralat berlaku atau pengecualian dilemparkan semasa melaksanakan fungsi panggil balik menyelesaikan, ia tidak akan menghentikan pelaksanaan. Sebaliknya, ia akan memasuki kaedah tangkapan.
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.
Atas ialah kandungan terperinci Javascript: Panduan Lengkap Janji. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!