


Menganalisis panggilan balik dan corak reka bentuk kod dalam Node.js pengaturcaraan tak segerak_node.js
Titik jualan terbesar NodeJS - mekanisme acara dan IO tak segerak, tidak telus kepada pembangun. Pembangun perlu menulis kod secara tidak segerak untuk memanfaatkan titik jualan ini, yang telah dikritik oleh beberapa lawan NodeJS. Tetapi tidak kira apa, pengaturcaraan tak segerak sememangnya ciri terbesar NodeJS Tanpa menguasai pengaturcaraan tak segerak, anda tidak boleh mengatakan bahawa anda telah benar-benar mempelajari NodeJS. Bab ini akan memperkenalkan pelbagai pengetahuan berkaitan pengaturcaraan tak segerak.
Dalam kod, manifestasi langsung pengaturcaraan tak segerak ialah panggilan balik. Pengaturcaraan tak segerak bergantung pada panggilan balik, tetapi tidak boleh dikatakan bahawa program menjadi tak segerak selepas menggunakan panggilan balik. Mula-mula kita boleh melihat kod berikut.
function heavyCompute(n, callback) { var count = 0, i, j; for (i = n; i > 0; --i) { for (j = n; j > 0; --j) { count += 1; } } callback(count); } heavyCompute(10000, function (count) { console.log(count); }); console.log('hello');
100000000 hello
Seperti yang anda lihat, fungsi panggil balik dalam kod di atas masih dilaksanakan sebelum kod berikutnya. JS sendiri berjalan dalam satu utas, dan adalah mustahil untuk menjalankan kod lain sebelum sekeping kod selesai dijalankan, jadi tiada konsep pelaksanaan tak segerak.
Walau bagaimanapun, jika fungsi yang dilakukan adalah untuk mencipta urutan atau proses lain, lakukan sesuatu selari dengan utas utama JS, dan maklumkan utas utama JS apabila perkara itu selesai, maka situasinya berbeza. Mari kita lihat kod berikut.
setTimeout(function () { console.log('world'); }, 1000); console.log('hello');
hello world
Kali ini anda boleh melihat bahawa fungsi panggil balik dilaksanakan selepas kod berikutnya. Seperti yang dinyatakan di atas, JS sendiri adalah satu-benang dan tidak boleh dilaksanakan secara tak segerak Oleh itu, kita boleh berfikir bahawa fungsi khas yang disediakan oleh persekitaran berjalan di luar spesifikasi JS seperti setTimeout lakukan adalah untuk mencipta benang selari dan kembali dengan serta-merta. JS master to Proses kemudiannya boleh melaksanakan kod berikutnya dan melaksanakan fungsi panggil balik selepas menerima pemberitahuan daripada proses selari. Sebagai tambahan kepada yang biasa seperti setTimeout dan setInterval, fungsi tersebut juga termasuk API tak segerak yang disediakan oleh NodeJS seperti fs.readFile.
Selain itu, kami masih kembali kepada fakta bahawa JS berjalan dalam satu urutan, yang menentukan bahawa JS tidak boleh melaksanakan kod lain, termasuk fungsi panggil balik, sebelum melaksanakan sekeping kod. Dalam erti kata lain, walaupun jika utas selari menyelesaikan kerjanya dan memberitahu utas utama JS untuk melaksanakan fungsi panggil balik, fungsi panggil balik tidak akan memulakan pelaksanaan sehingga utas utama JS melahu. Berikut adalah contoh sedemikian.
function heavyCompute(n) { var count = 0, i, j; for (i = n; i > 0; --i) { for (j = n; j > 0; --j) { count += 1; } } } var t = new Date(); setTimeout(function () { console.log(new Date() - t); }, 1000); heavyCompute(50000);
8520
Seperti yang anda lihat, masa pelaksanaan sebenar fungsi panggil balik yang sepatutnya dipanggil selepas 1 saat telah sangat tertangguh kerana utas utama JS sedang sibuk menjalankan kod lain.
Corak Reka Bentuk Kod
Pengaturcaraan tak segerak mempunyai banyak corak reka bentuk kod yang unik Untuk mencapai fungsi yang sama, kod yang ditulis dalam mod segerak dan mod tak segerak akan sangat berbeza. Beberapa corak biasa diperkenalkan di bawah.
Nilai pulangan fungsi
Ia adalah keperluan yang sangat biasa untuk menggunakan output satu fungsi sebagai input fungsi lain Dalam mod segerak, kod biasanya ditulis seperti berikut:
var output = fn1(fn2('input')); // Do something.
Dalam mod tak segerak, memandangkan hasil pelaksanaan fungsi tidak dihantar melalui nilai pulangan, tetapi melalui fungsi panggil balik, kod biasanya ditulis dengan cara berikut:
fn2('input', function (output2) { fn1(output2, function (output1) { // Do something. }); });
Seperti yang anda lihat, kaedah ini ialah satu fungsi panggil balik yang bersarang dalam satu fungsi panggil balik Jika terdapat terlalu banyak, ia adalah mudah untuk menulis kod berbentuk >.
Lintas tatasusunan
Apabila melintasi tatasusunan, ia juga merupakan keperluan biasa untuk menggunakan fungsi untuk melaksanakan beberapa pemprosesan pada ahli data mengikut turutan. Jika fungsi dilaksanakan secara serentak, kod berikut biasanya akan ditulis:
var len = arr.length, i = 0; for (; i < len; ++i) { arr[i] = sync(arr[i]); } // All array items have processed.
Jika fungsi dilaksanakan secara tidak segerak, kod di atas tidak dapat menjamin bahawa semua ahli tatasusunan telah diproses selepas gelung tamat. Jika ahli tatasusunan mesti diproses secara bersiri satu demi satu, kod tak segerak biasanya ditulis seperti berikut:
(function next(i, len, callback) { if (i < len) { async(arr[i], function (value) { arr[i] = value; next(i + 1, len, callback); }); } else { callback(); } }(0, arr.length, function () { // All array items have processed. }));
Seperti yang anda lihat, kod di atas hanya lulus dalam ahli tatasusunan seterusnya dan memulakan pusingan pelaksanaan seterusnya selepas fungsi tak segerak dilaksanakan sekali dan mengembalikan hasil pelaksanaan Sehingga semua ahli tatasusunan diproses, pelaksanaan kod berikutnya dicetuskan melalui panggilan balik.
Jika ahli tatasusunan boleh diproses secara selari, tetapi kod berikutnya masih memerlukan semua ahli tatasusunan diproses sebelum mereka boleh dilaksanakan, kod tak segerak akan dilaraskan kepada bentuk berikut:
(function (i, len, count, callback) { for (; i < len; ++i) { (function (i) { async(arr[i], function (value) { arr[i] = value; if (++count === len) { callback(); } }); }(i)); } }(0, arr.length, 0, function () { // All array items have processed. }));
Seperti yang anda lihat, berbanding dengan versi traversal bersiri tak segerak, kod di atas memproses semua ahli tatasusunan secara selari dan menggunakan pemboleh ubah pembilang untuk menentukan bila semua ahli tatasusunan telah diproses.
Pengendalian pengecualian
Mekanisme penangkapan dan pengendalian pengecualian yang disediakan oleh JS sendiri - cuba..tangkap.., hanya boleh digunakan untuk kod yang dilaksanakan secara serentak. Di bawah adalah contoh.
function sync(fn) { return fn(); } try { sync(null); // Do something. } catch (err) { console.log('Error: %s', err.message); }
Error: object is not a function
Seperti yang anda lihat, pengecualian akan menggelembung di sepanjang laluan pelaksanaan kod sehingga ia ditangkap apabila ia menemui pernyataan percubaan pertama. Walau bagaimanapun, oleh kerana fungsi tak segerak mengganggu laluan pelaksanaan kod, apabila pengecualian dijana semasa dan selepas pelaksanaan fungsi tak segerak menggelembung ke lokasi di mana laluan pelaksanaan terganggu, jika tiada kenyataan cuba ditemui, ia akan dilemparkan sebagai pengecualian global . Di bawah adalah contoh.
function async(fn, callback) { // Code execution path breaks here. setTimeout(function () { callback(fn()); }, 0); } try { async(null, function (data) { // Do something. }); } catch (err) { console.log('Error: %s', err.message); }
/home/user/test.js:4 callback(fn()); ^ TypeError: object is not a function at null._onTimeout (/home/user/test.js:4:13) at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
因为代码执行路径被打断了,我们就需要在异常冒泡到断点之前用 try 语句把异常捕获住,并通过回调函数传递被捕获的异常。于是我们可以像下边这样改造上边的例子。
function async(fn, callback) { // Code execution path breaks here. setTimeout(function () { try { callback(null, fn()); } catch (err) { callback(err); } }, 0); } async(null, function (err, data) { if (err) { console.log('Error: %s', err.message); } else { // Do something. } });
Error: object is not a function
可以看到,异常再次被捕获住了。在 NodeJS 中,几乎所有异步 API 都按照以上方式设计,回调函数中第一个参数都是 err。因此我们在编写自己的异步函数时,也可以按照这种方式来处理异常,与 NodeJS 的设计风格保持一致。
有了异常处理方式后,我们接着可以想一想一般我们是怎么写代码的。基本上,我们的代码都是做一些事情,然后调用一个函数,然后再做一些事情,然后再调用一个函数,如此循环。如果我们写的是同步代码,只需要在代码入口点写一个 try 语句就能捕获所有冒泡上来的异常,示例如下。
function main() { // Do something. syncA(); // Do something. syncB(); // Do something. syncC(); } try { main(); } catch (err) { // Deal with exception. }
但是,如果我们写的是异步代码,就只有呵呵了。由于每次异步函数调用都会打断代码执行路径,只能通过回调函数来传递异常,于是我们就需要在每个回调函数里判断是否有异常发生,于是只用三次异步函数调用,就会产生下边这种代码。
function main(callback) { // Do something. asyncA(function (err, data) { if (err) { callback(err); } else { // Do something asyncB(function (err, data) { if (err) { callback(err); } else { // Do something asyncC(function (err, data) { if (err) { callback(err); } else { // Do something callback(null); } }); } }); } }); } main(function (err) { if (err) { // Deal with exception. } });
可以看到,回调函数已经让代码变得复杂了,而异步方式下对异常的处理更加剧了代码的复杂度。

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

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Bagaimana untuk mengendalikan muat naik fail? Artikel berikut akan memperkenalkan kepada anda cara menggunakan ekspres untuk mengendalikan muat naik fail dalam projek nod saya harap ia akan membantu anda!

Artikel ini akan berkongsi dengan anda alat pengurusan proses Node "pm2", dan bercakap tentang mengapa pm2 diperlukan, cara memasang dan menggunakan pm2, saya harap ia akan membantu semua orang!

Penjelasan dan Panduan Pemasangan Terperinci untuk Pinetwork Nodes Artikel ini akan memperkenalkan ekosistem pinetwork secara terperinci - nod pi, peranan utama dalam ekosistem pinetwork, dan menyediakan langkah -langkah lengkap untuk pemasangan dan konfigurasi. Selepas pelancaran Rangkaian Ujian Blockchain Pinetwork, nod PI telah menjadi bahagian penting dari banyak perintis yang aktif mengambil bahagian dalam ujian, bersiap sedia untuk pelepasan rangkaian utama yang akan datang. Jika anda tidak tahu kerja pinet, sila rujuk apa itu picoin? Berapakah harga untuk penyenaraian? Penggunaan PI, perlombongan dan analisis keselamatan. Apa itu Pinetwork? Projek Pinetwork bermula pada tahun 2019 dan memiliki syiling pi cryptocurrency eksklusifnya. Projek ini bertujuan untuk mewujudkan satu yang semua orang boleh mengambil bahagian

Aplikasi Pantas: Analisis Kes Pembangunan Praktikal PHP Asynchronous HTTP Muat Turun Berbilang Fail Dengan pembangunan Internet, fungsi muat turun fail telah menjadi salah satu keperluan asas bagi banyak laman web dan aplikasi. Untuk senario di mana berbilang fail perlu dimuat turun pada masa yang sama, kaedah muat turun segerak tradisional selalunya tidak cekap dan memakan masa. Atas sebab ini, menggunakan PHP untuk memuat turun berbilang fail secara tidak segerak melalui HTTP telah menjadi penyelesaian yang semakin biasa. Artikel ini akan menganalisis secara terperinci cara menggunakan HTTP tak segerak PHP melalui kes pembangunan sebenar.

Pengesahan adalah salah satu bahagian terpenting dalam mana-mana aplikasi web. Tutorial ini membincangkan sistem pengesahan berasaskan token dan cara ia berbeza daripada sistem log masuk tradisional. Pada penghujung tutorial ini, anda akan melihat demo berfungsi sepenuhnya yang ditulis dalam Angular dan Node.js. Sistem Pengesahan Tradisional Sebelum beralih kepada sistem pengesahan berasaskan token, mari kita lihat sistem pengesahan tradisional. Pengguna memberikan nama pengguna dan kata laluan mereka dalam borang log masuk dan klik Log Masuk. Selepas membuat permintaan, sahkan pengguna di bahagian belakang dengan menanyakan pangkalan data. Jika permintaan itu sah, sesi dibuat menggunakan maklumat pengguna yang diperoleh daripada pangkalan data dan maklumat sesi dikembalikan dalam pengepala respons supaya ID sesi disimpan dalam penyemak imbas. Menyediakan akses kepada aplikasi tertakluk kepada

Dengan pembangunan dan pempopularan Internet yang berterusan, e-mel telah menjadi bahagian yang amat diperlukan dalam kehidupan dan pekerjaan orang ramai, dan SMTP (Simple Mail Transfer Protocol) ialah salah satu protokol penting untuk penghantaran e-mel. Sebagai rangka kerja komunikasi rangkaian tak segerak untuk PHP, Swoole boleh menyokong operasi SMTP tak segerak, menjadikan penghantaran e-mel lebih cekap dan stabil. Artikel ini akan memperkenalkan cara Swoole menyokong operasi SMTP tak segerak, termasuk menggunakan

Memandangkan volum perniagaan Internet terus berkembang, permintaan untuk keselarasan tinggi dan prestasi tinggi semakin tinggi dan lebih tinggi, dan Swoole, sebagai rangka kerja komunikasi rangkaian untuk PHP, semakin digemari oleh pembangun. Antaranya, Swoole menyokong AMQP tak segerak, yang merupakan salah satu senario aplikasi yang lebih biasa. Jadi mari kita lihat bagaimana Swoole menyokong operasi AMQP tak segerak. Pertama, kita perlu menjelaskan apa itu AMQP. AMQP (AdvancedMessageQueuingProtocol) Advanced

Pengaturcaraan Serentak dan Tak Segerak Pengaturcaraan serentak berurusan dengan berbilang tugas yang dilaksanakan secara serentak, pengaturcaraan tak segerak ialah sejenis pengaturcaraan serentak di mana tugasan tidak menyekat benang. asyncio ialah perpustakaan untuk pengaturcaraan tak segerak dalam python, yang membolehkan atur cara melaksanakan operasi I/O tanpa menyekat utas utama. Gelung peristiwa Teras asyncio ialah gelung peristiwa, yang memantau peristiwa I/O dan menjadualkan tugas yang sepadan. Apabila coroutine sedia, gelung acara melaksanakannya sehingga ia menunggu operasi I/O. Ia kemudian menjeda coroutine dan terus melaksanakan coroutine lain. Coroutines Coroutines ialah fungsi yang boleh menjeda dan menyambung semula pelaksanaan. Kata kunci asyncdef digunakan untuk membuat coroutine. Coroutine menggunakan kata kunci tunggu untuk menunggu operasi I/O selesai. Asas asyncio berikut
