Rumah  >  Artikel  >  hujung hadapan web  >  Ringkasan dan perkongsian untuk memahami beberapa nod utama nodej

Ringkasan dan perkongsian untuk memahami beberapa nod utama nodej

青灯夜游
青灯夜游ke hadapan
2022-07-06 20:36:502133semak imbas

Ringkasan dan perkongsian untuk memahami beberapa nod utama nodej

Artikel ini ialah beberapa pemahaman peribadi tentang nodejs dalam pembangunan dan pembelajaran sebenar Ia kini disusun untuk rujukan masa hadapan.

I/O tidak menyekat

I/O: Input / Output, input dan output sistem.

Sistem boleh difahami sebagai individu, seperti seseorang Apabila anda bercakap, ia adalah output, dan apabila anda mendengar, ia adalah input.

Perbezaan antara menyekat I/O dan tidak menyekat I/O terletak pada sama ada sistem boleh menerima input lain dalam tempoh dari input ke output.

Berikut ialah dua contoh untuk menggambarkan apa itu menyekat I/O dan tidak menyekat I/O:

1 >

Mula-mula kita perlu menentukan skop sistem Dalam contoh ini, makcik kantin dan pelayan di restoran dianggap sebagai sistem

Input sedang memesan, dan output sedang dihidangkan makananRingkasan dan perkongsian untuk memahami beberapa nod utama nodej.

Kemudian sama ada anda boleh menerima pesanan orang lain antara memesan dan menghidangkan makanan, anda boleh menentukan sama ada ia menyekat I/O atau tidak menyekat I/O. Makcik kafeteria pula, apabila dia sedang menempah, dia tidak boleh memesan untuk pelajar lain hanya selepas pelajar itu selesai memesan dan menghidangkan hidangan, barulah dia boleh menerima tempahan pelajar seterusnya, jadi makcik kafeteria sedang Menghalang. I/O.

Untuk pelayan restoran, dia boleh melayan tetamu seterusnya selepas membuat pesanan dan sebelum tetamu menghidangkan hidangan, jadi pelayan mempunyai I/O yang tidak menghalang.

2. Buat kerja rumah

Bila basuh baju, tak perlu tunggu dekat mesin basuh pergi ke sana pada masa ini Sapu lantai dan mengemas meja Apabila meja dikemas dan pakaian dicuci, gantung pakaian untuk mengeringkan Ia hanya mengambil masa 25 minit.

Ringkasan dan perkongsian untuk memahami beberapa nod utama nodejMencuci sebenarnya adalah I/O yang tidak menyekat Anda boleh melakukan perkara lain antara memasukkan pakaian ke dalam mesin basuh dan menyelesaikan pembasuhan.

Sebab I/O yang tidak menyekat boleh meningkatkan prestasi ialah ia boleh menjimatkan menunggu yang tidak perlu.

Kunci untuk memahami I/O tidak menyekat ialah :

Tentukan sempadan sistem untuk I/O

. Ini sangat kritikal jika sistem diperluaskan, seperti contoh restoran di atas, jika sistem diperluaskan ke seluruh restoran, maka chef pasti akan menjadi I/O yang menyekat.
  • Semasa proses I/O, bolehkah I/O lain dilakukan?
  • I/O yang tidak menyekat nodejs

Bagaimanakah I/O yang tidak menyekat nodejs dicerminkan? Seperti yang dinyatakan sebelum ini, perkara penting dalam memahami I/O tidak menyekat adalah dengan terlebih dahulu menentukan sempadan sistem. Sempadan sistem nod ialah

benang utama

. Jika gambar rajah seni bina di bawah dibahagikan mengikut penyelenggaraan benang, garis putus-putus di sebelah kiri ialah benang nodejs dan garis putus-putus di sebelah kanan ialah benang c.

Sekarang benang nodejs perlu menanyakan pangkalan data Ini adalah operasi I/O biasa Ia tidak akan menunggu hasil I/O dan terus memproses operasi lain Ia akan mengagihkan sejumlah besar kuasa pengkomputeran kepada benang c lain untuk pengiraan.

Ringkasan dan perkongsian untuk memahami beberapa nod utama nodejTunggu sehingga keputusan keluar dan kembalikan ke utas nodejs Sebelum mendapat keputusan, utas nodejs juga boleh melakukan operasi I/O lain, jadi ia tidak menyekat.

benang nodejs

bersamaan dengan bahagian kiri sebagai pelayan dan benang c sebagai tukang masak.

Jadi, I/O tidak menyekat nod diselesaikan dengan memanggil urutan pekerja c.

Bagaimana untuk memberitahu benang nodejs apabila benang c memperoleh hasilnya? Jawapannya ialah didorong peristiwa.

Didorong peristiwa

Menyekat: Proses tidur semasa I/O dan menunggu I/O selesai sebelum meneruskan ke seterusnya langkah;

Tidak menyekat: Fungsi kembali serta-merta semasa I/O, dan proses tidak menunggu I/O selesai.

Kemudian bagaimana untuk mengetahui hasil yang dikembalikan, anda perlu menggunakan event driven.

Apa yang dipanggil event-driven boleh difahamkan sama seperti acara klik hadapan saya mula-mula menulis acara klik, tetapi saya tidak tahu bila ia akan berlaku dicetuskan. Saya hanya membiarkan utas utama melaksanakan acara apabila ia dicetuskan.

Mod ini juga merupakan mod pemerhati, iaitu, saya mula-mula mendengar acara, dan kemudian melaksanakannya apabila ia dicetuskan. Jadi bagaimana untuk melaksanakan pemacu acara? Jawapannya ialah

Asynchronous Programming

.

Pengaturcaraan Asynchronous

Seperti yang dinyatakan di atas, nodejs mempunyai sejumlah besar I/O tidak menyekat, jadi hasil I/O tidak menyekat perlu diperoleh melalui fungsi panggil balik Kaedah menggunakan fungsi panggil balik ini ialah pengaturcaraan tak segerak . Contohnya, kod berikut memperoleh hasil melalui fungsi panggil balik:

glob(__dirname+'/**/*', (err, res) => {
    result = res
    console.log('get result')
})

Spesifikasi format fungsi panggil balik

Parameter pertama fungsi panggil balik nodejs ialah ralat, dan parameter seterusnya ialah hasilnya. Mengapa melakukan ini?

try {
  interview(function () {
       console.log('smile')
  })
} catch(err) {
    console.log('cry', err)
}

function interview(callback) {
    setTimeout(() => {
        if(Math.random() <p>Selepas pelaksanaan, ia tidak ditangkap dan ralat telah dilemparkan secara global, menyebabkan keseluruhan program nodejs ranap. </p><p><img src="https://img.php.cn/upload/image/244/886/980/1657110712466688.png" title="1657110712466688.png" alt="Ringkasan dan perkongsian untuk memahami beberapa nod utama nodej"></p><p> tidak ditangkap oleh try catch kerana setTimeout membuka semula gelung peristiwa Setiap kali gelung peristiwa dibuka, konteks tindanan panggilan dijana semula gelung. Apabila fungsi panggil balik setTimeout dilaksanakan, timbunan panggilan adalah berbeza. Untuk butiran, sila rujuk artikel ini <a href="https://juejin.cn/post/6995749646366670855" target="_blank" title="https://juejin.cn/post/6995749646366670855"> Masalah apabila menggunakan baris gilir tak segerak untuk cuba tangkap </a>. </p><p>Jadi apa yang perlu kita lakukan? Gunakan ralat sebagai parameter: </p><pre class="brush:php;toolbar:false">function interview(callback) {
    setTimeout(() => {
        if(Math.random() <p>Tetapi ini lebih menyusahkan, dan ia perlu dinilai dalam panggilan balik, jadi konvensyen matang dibuat jika ia tidak wujud , ia bermakna Pelaksanaan berjaya. </p><pre class="brush:php;toolbar:false">function interview(callback) {
    setTimeout(() => {
        if(Math.random() <h3 data-id="heading-5"><strong>Kawalan proses tak segerak</strong></h3><p>Kaedah penulisan panggil balik nodejs bukan sahaja akan membawa kawasan panggil balik, tetapi juga membawa soalan <strong>kawalan proses tak segerak</strong> . </p><p>Kawalan proses tak segerak terutamanya merujuk kepada cara mengendalikan logik konkurensi apabila konkurensi berlaku. Masih menggunakan contoh di atas, jika rakan sekerja anda menemuduga dua syarikat, dia tidak akan ditemuduga oleh syarikat ketiga sehingga dia berjaya menemuduga dua syarikat. Jadi bagaimana untuk menulis logik ini? Ia adalah perlu untuk menyokong setiap kiraan pembolehubah secara global: </p><pre class="brush:php;toolbar:false">var count = 0
interview((err) => {
    if (err) {
        return
    }
    count++
    if (count >= 2) {
        // 处理逻辑
    }
})

interview((err) => {
    if (err) {
        return
    }
    count++
    if (count >= 2) {
        // 处理逻辑
    }
})

Menulis seperti di atas sangat menyusahkan dan hodoh. Oleh itu, kaedah penulisan janji dan async/menunggu muncul kemudian.

janji

Gelung peristiwa semasa tidak boleh mendapatkan hasil, tetapi gelung acara masa hadapan akan memberikan hasil kepada anda. Ia sangat serupa dengan apa yang akan dikatakan oleh seorang bajingan.

janji bukan sahaja sampah, tetapi juga mesin negara:

  • pending
  • ditepati/diselesaikan
  • ditolak
const pro = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('2')
    }, 200)
})
console.log(pro) // 打印:Promise { <pending> }</pending>

kemudian & .tangkap

  • Janji dalam keadaan yang telah diselesaikan akan memanggil yang pertama kemudian
  • janji negeri yang ditolak The first catch
  • akan dipanggil. Sebarang janji dengan keadaan tolak dan tiada .catch di belakangnya akan menyebabkan ralat global dalam pelayar atau persekitaran nod. tidak ditangkap mewakili ralat yang tidak ditangkap.

Ringkasan dan perkongsian untuk memahami beberapa nod utama nodej

Melaksanakan kemudian atau menangkap akan mengembalikan janji baharu Keadaan akhir janji ditentukan oleh hasil pelaksanaan fungsi panggil balik daripada kemudian dan tangkap :

  • Jika fungsi panggil balik sentiasa membuang Ralat baharu, janji berada dalam keadaan ditolak
  • Jika fungsi panggil balik sentiasa dikembalikan, janji berada dalam keadaan diselesaikan
  • Tetapi jika Fungsi panggil balik sentiasa mengembalikan janji, dan janji akan konsisten dengan status janji yang dikembalikan oleh fungsi panggil balik .
function interview() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (Math.random() > 0.5) {
                resolve('success')
            } else {
                reject(new Error('fail'))
            }
        })
    })
}

var promise = interview()
var promise1 = promise.then(() => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('accept')
        }, 400)
    })
})

Status janji1 ditentukan oleh status janji sebagai balasan, iaitu status janji1 selepas janji sebagai balasan dilaksanakan. Apakah faedah ini? Ini boleh menyelesaikan masalah neraka panggil balik.

var promise = interview()
    .then(() => {
        return interview()
    })
    .then(() => {
        return interview()
    })
    .then(() => {
        return interview()
    })
    .catch(e => {
        console.log(e)
    })

kemudian Jika status janji yang dikembalikan itu ditolak, maka tangkapan pertama akan dipanggil, dan yang berikutnya tidak akan dipanggil. Ingat: menolak panggilan tangkapan pertama, dan menyelesaikan panggilan pertama kemudian.

Promise menyelesaikan kawalan proses tak segerak

Jika janji hanya untuk menyelesaikan panggilan balik neraka, ia adalah terlalu kecil untuk meremehkan janji Fungsi utama janji adalah untuk menyelesaikan proses tak segerak masalah kawalan. Jika anda ingin menemu bual dua syarikat pada masa yang sama:

function interview() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (Math.random() > 0.5) {
                resolve('success')
            } else {
                reject(new Error('fail'))
            }
        })
    })
}

promise
    .all([interview(), interview()])
    .then(() => {
        console.log('smile')
    })
    // 如果有一家公司rejected,就catch
    .catch(() => {
        console.log('cry')
    })

async/menunggu

Apakah sebenarnya penyegerakan/menunggu:

console.log(async function() {
    return 4
})

console.log(function() {
    return new Promise((resolve, reject) => {
        resolve(4)
    })
})

Cetak Hasilnya adalah sama iaitu async/wait hanyalah syntactic sugar for promise.

Kami tahu bahawa cuba tangkap menangkap ralat bergantung pada tindanan panggilan dan hanya boleh menangkap ralat di atas tindanan panggilan. Tetapi jika anda menggunakan await, anda boleh menangkap ralat dalam semua fungsi dalam timbunan panggilan. Walaupun ralat dilemparkan dalam timbunan panggilan gelung acara lain, seperti setTimeout.

Ubah suai kod temu duga dan anda boleh melihat bahawa kod itu lebih diperkemas.

try {
    await interview(1)
    await interview(2)
    await interview(2)
} catch(e => {
    console.log(e)
})

Bagaimana jika ia adalah tugasan yang selari?

await Promise.all([interview(1), interview(2)])

Gelung peristiwa

Oleh kerana I/0 nodej yang tidak menyekat, adalah perlu untuk menggunakan kaedah dipacu peristiwa untuk mendapatkan I/ Hasil O dan laksanakan pemerolehan dipacu peristiwa Pengaturcaraan tak segerak, seperti fungsi panggil balik, mesti digunakan untuk mendapatkan hasilnya. Jadi bagaimana untuk melaksanakan fungsi panggil balik ini untuk mendapatkan hasilnya? Kemudian anda perlu menggunakan gelung acara.

Gelung peristiwa ialah asas utama untuk merealisasikan fungsi I/O tidak menyekat nodej dan gelung peristiwa adalah kedua-dua keupayaan yang disediakan oleh perpustakaan libuv.

Ringkasan dan perkongsian untuk memahami beberapa nod utama nodej

代码演示:

const eventloop = {
    queue: [],
    loop() {
        while(this.queue.length) {
            const callback = this.queue.shift()
            callback()
        }
        setTimeout(this.loop.bind(this), 50)
    },
    add(callback) {
        this.queue.push(callback)
    }
}

eventloop.loop()

setTimeout(() => {
    eventloop.add(() => {
        console.log('1')
    })
}, 500)

setTimeout(() => {
	eventloop.add(() => {
		console.log('2')
	})
}, 800)

setTimeout(this.loop.bind(this), 50)保证了50ms就会去看队列中是否有回调,如果有就去执行。这样就形成了一个事件循环。

当然实际的事件要复杂的多,队列也不止一个,比如有一个文件操作对列,一个时间对列。

const eventloop = {
    queue: [],
    fsQueue: [],
    timerQueue: [],
    loop() {
        while(this.queue.length) {
            const callback = this.queue.shift()
            callback()
        }
        this.fsQueue.forEach(callback => {
            if (done) {
                callback()
            }
        })
        setTimeout(this.loop.bind(this), 50)
    },
    add(callback) {
        this.queue.push(callback)
    }
}

总结

首先我们弄清楚了什么是非阻塞I/O,即遇到I/O立刻跳过执行后面的任务,不会等待I/O的结果。当I/O处理好了之后就会调用我们注册的事件处理函数,这就叫事件驱动。实现事件驱动就必须要用异步编程,异步编程是nodejs中最重要的环节,它从回调函数到promise,最后到async/await(使用同步的方法写异步逻辑)。

更多node相关知识,请访问:nodejs 教程

Atas ialah kandungan terperinci Ringkasan dan perkongsian untuk memahami beberapa nod utama nodej. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:juejin.cn. Jika ada pelanggaran, sila hubungi admin@php.cn Padam