Semua acara socketio yang masuk akan mula diproses mengikut susunan yang tiba. Mereka yang mempunyai fungsi pengendali segerak dijamin untuk menyelesaikan pemprosesan dalam susunan yang sama. Walau bagaimanapun, itu mungkin tidak berlaku untuk acara dengan pengendali tak segerak, yang boleh menyelesaikan pemprosesan dalam sebarang susunan. Tingkah laku ini menjadikan kod kami lebih pantas, tetapi dalam sesetengah kes, mungkin bukan yang kami mahukan.
Dalam siaran pendek ini, anda akan belajar cara membuat acara dengan tugas tak segerak memulakan dan menyelesaikan pemprosesan mengikut urutan ia tiba di pelayan. Untuk mencapai matlamat ini, kami akan mencipta sistem baris gilir tersuai yang mudah.
Jom selami.
Anggapkan anda mempunyai situasi di mana dua pelanggan disambungkan ke pelayan socketio anda. Anda mahukan gelagat di mana yang pertama menghantar acara mencipta baris baharu dalam jadual pangkalan data dan yang kedua mengemas kini baris yang sama. Kod anda mungkin kelihatan seperti ini:
io.on("connection", (socket) => { console.log("A user connected"); socket.on("SOME_EVENT", async(param) => { //check whether the column already exists: const column = await db.select... //if column exists, update it: if(column){ await db.update... } //else, create one await db.insert... }) }
Sekarang, masalahnya ialah jika kedua-dua pelanggan memancarkan "SOME_EVENT" serentak, ada kemungkinan mereka berdua akan membuat baris baharu dalam pangkalan data, yang bukan yang kita mahukan.
Daripada membenarkan socketio melaksanakan fungsi pengendali, kami akan memintasnya dan memutuskan bila ia dilaksanakan. Apabila kami memintas pengendali, kami akan menghantar mereka ke sistem baris gilir kami, yang bertanggungjawab untuk melaksanakannya dengan teratur.
Sistem ini akan mempunyai dua komponen utama — baris gilir dan gelung acara.
Dalam sains komputer, baris gilir ialah struktur data yang membolehkan kami menyimpan dan mengurus data secara berurutan. Untuk mencapai matlamat ini, struktur hanya membenarkan data ditambah pada satu hujung (ekor) dan keluar pada hujung yang lain (kepala). Ciri ini lebih popular dipanggil FIFO, yang bermaksud pertama masuk dahulu.
Baris gilir ialah jenis data abstrak (ADT). Seperti ADT lain, banyak bahasa pengaturcaraan, termasuk Javascript, tidak memilikinya secara lalai. Dalam siaran ini, kami akan memodelkan baris gilir kami menggunakan kaedah unshift dan pop tatasusunan Javascript.
Dalam istilah umum, gelung peristiwa ialah binaan yang berjalan pada selang waktu dan melaksanakan tugas secara bersyarat. Kami akan menggunakan setInterval dalam kes kami, yang akan sentiasa menyemak sama ada baris gilir mengandungi fungsi yang belum selesai dan akan memanggil fungsi seterusnya hanya apabila yang sebelumnya selesai.
class QueuingSystem { //We're making the queue private so that it can only be //modified only within the class #queue = []; constructor(interval) { this.interval = interval; } //returns last item of an array: lastItem(arr) { return arr[arr.length - 1]; } //returns true if array is empty: isEmpty(arr) { return arr.length == 0; } //responsible for executing the function at the head of the queue: async run(arr) { //removing the function at the head of the queue: const func = arr.pop(); //adding "false" placeholder at the head to indicate that //a function is being executed: arr.push(false); //executing the function: await func(); //removing the false placeholder at the head to indicate that //the run function is ready to execute the next function: arr.pop(); } //function to add to the tail end of the queue: addToQueue(func) { this.#queue.unshift(func); } //function to start the event loop: start() { return setInterval(() => { //checking if the run method is free by checking if the item at the head is false. //and checking if the array isn't empty if (this.lastItem(this.#queue) !== false && !this.isEmpty(this.#queue)) { this.run(this.#queue); } }, this.interval); } //stopping the event loop if no longer needed: stop() { clearInterval(this.start()); } }
Kelas baris gilir mesej kami kini bersedia untuk menerima dan melaksanakan fungsi secara berurutan.
Dengan sistem baris gilir kami disediakan, mari gunakannya dalam kod kami:
//Create a socketQueue that loops after every half of a second: const socketQueue = new QueuingSystem(500) io.on("connection", (socket) => { console.log("A user connected"); const handler = async(param) => { //check whether the column already exists: const column = await db.select... //if column exists, update it: if(column){ await db.update... } //else, create one await db.insert... } socket.on("SOME_EVENT", (param) => { //Add the handler function to socketQueue queue socketQueue.addToQueue(hanlder.bind(null, param)) }) } server.listen(PORT, () => { //start the queuing system: socketQueue.start(); console.log("App listening on port", PORT); });
Kaedah bind dalam Javascript digunakan untuk melampirkan fungsi, bersama dengan parameternya, pada objek, tetapi tidak memanggilnya. Dalam kes kami, kami tidak melampirkan fungsi pada sebarang objek, itulah sebabnya hujah pertama adalah batal.
Kelas baris gilir mesej yang kami buat boleh membantu kami melaksanakan acara dengan pengendali tak segerak secara berurutan. Jika anda memerlukan sistem baris gilir yang lebih kompleks, lihat BullMQ atau penyelesaian teguh lain. Selamat mengekod!
Atas ialah kandungan terperinci Cara Mudah Mengendalikan Acara Socket.io dalam Urutan: Panduan Ringkas. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!