Kenapa?
Untuk mendapatkan idea bagaimana JavaScript Promises menjalankan panggilan balik secara tidak segerak di bawah hud.
Mari kita cipta Janji kita sendiri dalam JavaScript! Kami akan mengikut spesifikasi Promise/A, yang menggariskan cara janji mengendalikan operasi async, menyelesaikan, menolak dan memastikan pengendalian rantaian dan ralat yang boleh diramal.
Untuk memastikan perkara mudah, kami akan menumpukan pada peraturan utama yang ditandai dengan ✅ dalam spesifikasi Promises/A. Ini bukan pelaksanaan penuh, tetapi versi yang dipermudahkan. Inilah yang akan kami bina:
1. Terminologi
1.1 'janji' ialah objek atau fungsi dengan kaedah kemudian yang tingkah lakunya mematuhi spesifikasi ini.
1.2 thenable' ialah objek atau fungsi yang mentakrifkan kaedah kemudian.
1.3 'nilai' ialah mana-mana nilai JavaScript yang sah (termasuk tidak ditentukan, boleh kemudian atau janji).
1.4 'pengecualian' ialah nilai yang dilemparkan menggunakan pernyataan lontaran.
1.5 'sebab' ialah nilai yang menunjukkan sebab janji ditolak.
2. Keperluan
2.1 Negara Janji
Janji mestilah dalam salah satu daripada tiga keadaan: belum selesai, ditepati atau ditolak.
2.1.1. Apabila belum selesai, janji: ✅
⟶ boleh beralih kepada sama ada keadaan dipenuhi atau ditolak.
2.1.2. Apabila ditepati, janji: ✅
⟶ tidak boleh beralih ke mana-mana negeri lain.
⟶ mesti mempunyai nilai, yang tidak boleh berubah.
2.1.3. Apabila ditolak, janji: ✅
⟶ tidak boleh beralih ke mana-mana negeri lain.
⟶ mesti ada sebab, yang mesti tak berubah.
2.2 Kaedah kemudian
Janji mesti menyediakan kaedah kemudian untuk mengakses nilai atau sebab semasa atau akhirnya.
Kaedah janji menerima dua hujah:
promise.then(onFulfilled, onRejected);
2.2.1. Kedua-dua onFulfilled dan onRejected ialah hujah pilihan: ✅
⟶ Jika onFulfilled bukan fungsi, ia mesti diabaikan.
⟶ Jika onRejected bukan fungsi, ia mesti diabaikan.
2.2.2. Jika onFulfilled ialah fungsi: ✅
⟶ ia mesti dipanggil selepas janji dipenuhi, dengan nilai janji sebagai hujah pertamanya.
⟶ ia tidak boleh dipanggil sebelum janji ditepati.
⟶ ia tidak boleh dipanggil lebih daripada sekali.
2.2.3. Jika onRejected ialah fungsi, ✅
⟶ ia mesti dipanggil selepas janji ditolak, dengan alasan janji sebagai hujah pertamanya.
⟶ ia tidak boleh dipanggil sebelum janji ditolak.
⟶ ia tidak boleh dipanggil lebih daripada sekali.
2.2.4. onFulfilled atau onRejected tidak boleh dipanggil sehingga tindanan konteks pelaksanaan hanya mengandungi kod platform. ✅
2.2.5. onFulfilled dan onRejected mesti dipanggil sebagai fungsi (iaitu tanpa nilai ini). ✅
2.2.6. kemudian boleh dipanggil beberapa kali pada janji yang sama. ✅
⟶ Jika/apabila janji ditepati, semua panggilan balik onFulfilled masing-masing mesti dilaksanakan mengikut urutan panggilan asalnya pada masa itu.
⟶ Jika/apabila janji ditolak, semua panggilan balik onRejected masing-masing mesti dilaksanakan mengikut urutan panggilan asalnya pada masa itu.
2.2.7. maka mesti membalas janji. ✅
promise.then(onFulfilled, onRejected);
⟶ Jika sama ada onFulfilled atau onRejected mengembalikan nilai x, jalankan Prosedur Penyelesaian Janji [[Resolve]](promise2, x). ❌
⟶ Jika sama ada onFulfilled atau onRejected melemparkan pengecualian e, promise2 mesti ditolak dengan e sebagai alasan. ❌
⟶ Jika onFulfilled bukan fungsi dan promise1 dipenuhi, promise2 mesti ditunaikan dengan nilai yang sama seperti promise1. ❌
⟶ Jika onRejected bukan fungsi dan promise1 ditolak, promise2 mesti ditolak dengan alasan yang sama seperti promise1. ❌
Perlaksanaan
Janji JavaScript mengambil fungsi pelaksana sebagai hujah, yang dipanggil serta-merta apabila Janji dibuat:
promise2 = promise1.then(onFulfilled, onRejected);
new Promise(excecutor);
Spesifikasi teras Janji/A tidak berurusan dengan cara mencipta, memenuhi atau menolak janji. Terpulang kepada anda. Tetapi pelaksanaan yang anda sediakan untuk pembinaan janji harus serasi dengan API tak segerak dalam JavaScript. Berikut ialah draf pertama kelas Promise kami:
const promise = new Promise((resolve, reject) => { // Runs some async or sync tasks });
Peraturan 2.1 (Negara Janji) menyatakan bahawa janji mesti berada dalam salah satu daripada tiga keadaan: belum selesai, dipenuhi atau ditolak. Ia juga menerangkan perkara yang berlaku di setiap negeri ini.
Apabila dipenuhi atau ditolak, janji tidak boleh beralih ke mana-mana negeri lain. Oleh itu, kita perlu memastikan janji berada dalam keadaan belum selesai sebelum membuat sebarang peralihan:
class YourPromise { constructor(executor) { this.state = 'pending'; this.value = undefined; this.reason = undefined; const resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; } }; const reject = reason => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; } }; try { executor(resolve, reject); // The executor function being called immediately } catch (error) { reject(error); } } }
Kami sudah mengetahui bahawa keadaan awal janji belum selesai, dan kami memastikan ia kekal sehingga dipenuhi atau ditolak secara jelas:
const resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; } }; const reject = reason => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; } };
Memandangkan fungsi pelaksana dipanggil serta-merta selepas instantiasi janji, kami memanggilnya dalam kaedah pembina:
this.state = 'pending';
Draf pertama kelas YourPromise kami selesai di sini.
Spesifikasi Promise/A kebanyakannya tertumpu pada penentuan kaedah interoperable then() . Kaedah ini membolehkan kami mengakses nilai atau sebab semasa atau akhirnya janji itu. Mari kita mendalaminya.
Peraturan 2.2 (Kaedah kemudian) menyatakan bahawa janji mesti mempunyai kaedah then(), yang menerima dua hujah:
try { executor(resolve, reject); } catch (error) { reject(error); }
Kedua-dua onFulfilled dan onRejected mesti dipanggil selepas janji dipenuhi atau ditolak, melepasi nilai janji atau alasan sebagai hujah pertama mereka jika ia adalah fungsi:
class YourPromise { constructor(executor) { // Implementation } then(onFulfilled, onRejected) { // Implementation } }
Selain itu, mereka tidak boleh dipanggil sebelum janji ditunaikan atau ditolak, atau lebih daripada sekali. Kedua-dua onFulfilled dan onRejected adalah pilihan dan harus diabaikan jika ia bukan fungsi.
Jika anda melihat Peraturan 2.2, 2.2.6 dan 2.2.7, anda akan melihat bahawa janji mesti mempunyai kaedah then(), kaedah then() boleh dipanggil beberapa kali dan ia mesti mengembalikan a janji:
promise.then(onFulfilled, onRejected);
Untuk memastikan perkara mudah, kami tidak akan berurusan dengan kelas atau fungsi yang berasingan. Kami akan mengembalikan objek janji, melepasi fungsi pelaksana:
promise2 = promise1.then(onFulfilled, onRejected);
Dalam fungsi pelaksana, jika janji dipenuhi, kami memanggil panggilan balik onFulfilled dan menyelesaikannya dengan nilai janji. Begitu juga, jika janji ditolak, kami memanggil panggilan balik onRejected dan menolaknya dengan alasan janji itu.
Soalan seterusnya ialah apa yang perlu dilakukan dengan panggilan balik onFulfilled dan onRejected jika janji masih dalam keadaan belum selesai? Kami beratur untuk dipanggil kemudian, seperti berikut:
new Promise(excecutor);
Kami sudah selesai. Berikut ialah draf kedua kelas Promise kami, termasuk kaedah then():
const promise = new Promise((resolve, reject) => { // Runs some async or sync tasks });
Di sini, kami memperkenalkan dua medan: onFulfilledCallbacks dan onRejectedCallbacks sebagai baris gilir untuk menahan panggilan balik. Baris gilir ini diisi dengan panggilan balik melalui panggilan then() semasa janji belum selesai dan ia dipanggil apabila janji ditepati atau ditolak.
Teruskan uji kelas Promise anda:
class YourPromise { constructor(executor) { this.state = 'pending'; this.value = undefined; this.reason = undefined; const resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; } }; const reject = reason => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; } }; try { executor(resolve, reject); // The executor function being called immediately } catch (error) { reject(error); } } }
Ia sepatutnya mengeluarkan:
const resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; } }; const reject = reason => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; } };
Sebaliknya, jika anda menjalankan ujian berikut:
this.state = 'pending';
Anda akan mendapat:
try { executor(resolve, reject); } catch (error) { reject(error); }
Sebaliknya:
class YourPromise { constructor(executor) { // Implementation } then(onFulfilled, onRejected) { // Implementation } }
Kenapa? Isunya terletak pada cara kaedah then() memproses panggilan balik apabila contoh YourPromise sudah diselesaikan atau ditolak pada masa then() dipanggil. Khususnya, apabila keadaan janji tidak belum selesai, kaedah then() tidak menangguhkan pelaksanaan panggilan balik dengan betul ke baris gilir tugas mikro seterusnya. Dan itu menyebabkan pelaksanaan segerak. Dalam ujian contoh kami:
⟶ Janji segera diselesaikan dengan nilai 'Segera diselesaikan'.
⟶ Apabila promise.then() dipanggil keadaan sudah dipenuhi, jadi panggilan balik onFulfilled dilaksanakan terus tanpa ditunda ke baris gilir tugas mikro seterusnya.
Di sini Peraturan 2.2.4 mula dimainkan. Peraturan ini memastikan bahawa panggil balik then() (onFulfilled atau onRejected) dilaksanakan secara tidak segerak, walaupun janji telah diselesaikan atau ditolak. Ini bermakna panggilan balik tidak boleh dijalankan sehingga timbunan pelaksanaan semasa benar-benar jelas dan hanya kod platform (seperti gelung acara atau baris gilir tugas mikro) sedang dijalankan.
Mengapa peraturan ini penting?
Peraturan ini ialah salah satu peraturan terpenting dalam spesifikasi Promise/A. Kerana ia memastikan bahawa:
⟶ Walaupun janji diselesaikan serta-merta, panggilan balik then() itu tidak akan dilaksanakan sehingga tanda seterusnya bagi gelung acara.
⟶ Tingkah laku ini sejajar dengan kelakuan API tak segerak yang lain dalam JavaScript seperti setTimeout atau process.nextTick.
Bagaimanakah kita boleh mencapai ini?
Ini boleh dicapai sama ada dengan mekanisme tugasan makro seperti setTimeout atau setImmediate, atau dengan mekanisme tugasan mikro seperti queueMicrotask atau process.nextTick. Kerana panggilan balik dalam tugasan mikro atau tugasan makro atau mekanisme serupa akan dilaksanakan selepas konteks pelaksanaan JavaScript semasa selesai.
Untuk menyelesaikan isu di atas, kami perlu memastikan bahawa walaupun keadaan telah dipenuhi atau ditolak, panggilan balik yang sepadan (onFulfilled atau onRejected) dilaksanakan secara tidak segerak menggunakan queueMicrotask. Berikut ialah pelaksanaan yang diperbetulkan:
promise.then(onFulfilled, onRejected);
Jalankan semula kod ujian contoh sebelumnya. Anda sepatutnya mendapat output berikut:
promise2 = promise1.then(onFulfilled, onRejected);
Itu sahaja.
Setakat ini, anda sepatutnya mempunyai pemahaman yang jelas tentang cara panggilan balik dari then() ditangguhkan dan dilaksanakan dalam baris gilir tugas mikro seterusnya, yang membolehkan gelagat tak segerak. Pemahaman yang kukuh tentang konsep ini adalah penting untuk menulis kod tak segerak yang berkesan dalam JavaScript.
Apa yang seterusnya? Memandangkan artikel ini tidak merangkumi spesifikasi penuh Janji/A, anda boleh cuba melaksanakan yang lain untuk mendapatkan pemahaman yang lebih mendalam.
Memandangkan anda telah berjaya sejauh ini, semoga anda menikmati bacaannya! Sila kongsi artikel.
Ikuti saya di:
LinkedIn, Sederhana dan Github
Atas ialah kandungan terperinci Cipta Janji anda sendiri dalam JavaScript. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Node.js cemerlang pada I/O yang cekap, sebahagian besarnya terima kasih kepada aliran. Aliran memproses data secara berperingkat, mengelakkan beban memori-ideal untuk fail besar, tugas rangkaian, dan aplikasi masa nyata. Menggabungkan sungai dengan keselamatan jenis typescript mencipta powe

Perbezaan prestasi dan kecekapan antara Python dan JavaScript terutamanya dicerminkan dalam: 1) sebagai bahasa yang ditafsirkan, Python berjalan perlahan tetapi mempunyai kecekapan pembangunan yang tinggi dan sesuai untuk pembangunan prototaip pesat; 2) JavaScript adalah terhad kepada benang tunggal dalam penyemak imbas, tetapi I/O multi-threading dan asynchronous boleh digunakan untuk meningkatkan prestasi dalam node.js, dan kedua-duanya mempunyai kelebihan dalam projek sebenar.

JavaScript berasal pada tahun 1995 dan dicipta oleh Brandon Ike, dan menyedari bahasa itu menjadi C. 1.C Language menyediakan keupayaan pengaturcaraan prestasi tinggi dan sistem untuk JavaScript. 2. Pengurusan memori JavaScript dan pengoptimuman prestasi bergantung pada bahasa C. 3. Ciri lintas platform bahasa C membantu JavaScript berjalan dengan cekap pada sistem operasi yang berbeza.

JavaScript berjalan dalam penyemak imbas dan persekitaran Node.js dan bergantung pada enjin JavaScript untuk menghuraikan dan melaksanakan kod. 1) menjana pokok sintaks abstrak (AST) di peringkat parsing; 2) menukar AST ke bytecode atau kod mesin dalam peringkat penyusunan; 3) Laksanakan kod yang disusun dalam peringkat pelaksanaan.

Trend masa depan Python dan JavaScript termasuk: 1. Kedua -duanya akan terus mengembangkan senario aplikasi dalam bidang masing -masing dan membuat lebih banyak penemuan dalam prestasi.

Kedua -dua pilihan Python dan JavaScript dalam persekitaran pembangunan adalah penting. 1) Persekitaran pembangunan Python termasuk Pycharm, Jupyternotebook dan Anaconda, yang sesuai untuk sains data dan prototaip cepat. 2) Persekitaran pembangunan JavaScript termasuk node.js, vscode dan webpack, yang sesuai untuk pembangunan front-end dan back-end. Memilih alat yang betul mengikut keperluan projek dapat meningkatkan kecekapan pembangunan dan kadar kejayaan projek.

Ya, teras enjin JavaScript ditulis dalam C. 1) Bahasa C menyediakan prestasi yang efisien dan kawalan asas, yang sesuai untuk pembangunan enjin JavaScript. 2) Mengambil enjin V8 sebagai contoh, terasnya ditulis dalam C, menggabungkan kecekapan dan ciri-ciri berorientasikan objek C. 3) Prinsip kerja enjin JavaScript termasuk parsing, penyusun dan pelaksanaan, dan bahasa C memainkan peranan penting dalam proses ini.

JavaScript adalah di tengah -tengah laman web moden kerana ia meningkatkan interaktiviti dan dinamik laman web. 1) Ia membolehkan untuk menukar kandungan tanpa menyegarkan halaman, 2) memanipulasi laman web melalui Domapi, 3) menyokong kesan interaktif kompleks seperti animasi dan drag-and-drop, 4) mengoptimumkan prestasi dan amalan terbaik untuk meningkatkan pengalaman pengguna.


Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Dreamweaver CS6
Alat pembangunan web visual

EditPlus versi Cina retak
Saiz kecil, penyerlahan sintaks, tidak menyokong fungsi gesaan kod

Penyesuai Pelayan SAP NetWeaver untuk Eclipse
Integrasikan Eclipse dengan pelayan aplikasi SAP NetWeaver.

ZendStudio 13.5.1 Mac
Persekitaran pembangunan bersepadu PHP yang berkuasa

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa
