Misalkan Anda mempertahankan pustaka yang mengekspos suatu fungsi getData
. Pengguna Anda menyebutnya untuk mendapatkan data aktual:
var output = getData();
Di balik terpal data disimpan dalam file sehingga Anda menerapkannya getData
menggunakan Node.js bawaan fs.readFileSync
. Sudah jelas keduanya getData
dan fs.readFileSync
merupakan fungsi sinkronisasi. Suatu hari Anda diminta untuk mengalihkan sumber data yang mendasari ke repo seperti MongoDB yang hanya dapat diakses secara asinkron. Anda juga diberitahu untuk menghindari membuat pengguna Anda kesal, getData
API tidak dapat diubah untuk hanya mengembalikan sebuah janji atau meminta parameter callback. Bagaimana Anda memenuhi kedua persyaratan tersebut?
Fungsi asynchronous menggunakan callback / promise adalah DNA JavasSript dan Node.js. Aplikasi JS non-sepele apa pun mungkin diresapi dengan gaya pengkodean ini. Tapi praktik ini dapat dengan mudah mengarah pada apa yang disebut piramida malapetaka panggilan balik. Lebih buruk lagi, jika kode apa pun di pemanggil mana pun dalam rantai panggilan bergantung pada hasil dari fungsi asinkron, kode tersebut harus dibungkus dalam fungsi panggilan balik juga, sehingga menerapkan batasan gaya pengkodean pada pemanggil. Dari waktu ke waktu saya merasa perlu untuk merangkum fungsi async (sering disediakan di perpustakaan pihak ke-3) ke dalam fungsi sinkronisasi untuk menghindari pemfaktoran ulang global secara besar-besaran. Mencari solusi tentang masalah ini biasanya berakhir dengan Node Fibers atau paket npm yang diturunkan darinya. Tapi Serat tidak bisa menyelesaikan masalah yang saya hadapi. Bahkan contoh yang diberikan oleh penulis Fibers menggambarkan kekurangannya:
...
Fiber(function() {
console.log('wait... ' + new Date);
sleep(1000);
console.log('ok... ' + new Date);
}).run();
console.log('back in main');
Output aktual:
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
Jika fungsi Fiber benar-benar mengubah fungsi async menjadi sinkron, outputnya harus:
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
back in main
Saya telah membuat contoh sederhana lainnya di JSFiddle dan mencari kode untuk menghasilkan keluaran yang diharapkan. Saya akan menerima solusi yang hanya berfungsi di Node.js sehingga Anda bebas memerlukan paket npm apa pun meskipun tidak berfungsi di JSFiddle.
Jawaban:
deasync mengubah fungsi asinkron menjadi sinkron, diimplementasikan dengan mekanisme pemblokiran dengan memanggil event loop Node.js pada lapisan JavaScript. Akibatnya, deasync hanya memblokir kode berikutnya agar tidak berjalan tanpa memblokir seluruh utas, atau membuat menunggu sibuk. Dengan modul ini, berikut adalah jawaban dari tantangan jsFiddle:
(Penafian: Saya adalah penulis bersama
deasync
. Modul ini dibuat setelah memposting pertanyaan ini dan tidak menemukan proposal yang bisa diterapkan.)sumber
function AnticipatedSyncFunction(){ var ret; setTimeout(function(){ var startdate = new Date() //console.log(startdate) ret = "hello" + startdate; },3000); while(ret === undefined) { require('deasync').runLoopOnce(); } return ret; } var output = AnticipatedSyncFunction(); var startdate = new Date() console.log(startdate) console.log("output="+output);
dan saya berharap melihat 3 detik berbeda dalam keluaran tanggal!Ada juga modul sinkronisasi npm. yang digunakan untuk menyinkronkan proses menjalankan kueri.
Ketika Anda ingin menjalankan query paralel secara sinkron maka node membatasi untuk melakukan itu karena tidak pernah menunggu respon. dan modul sinkronisasi sangat cocok untuk solusi semacam itu.
Kode sampel
tautan referensi: https://www.npmjs.com/package/sync
sumber
Iya. Di dalam serat, fungsi menunggu sebelum masuk
ok
. Serat tidak membuat fungsi asinkron sinkron, tetapi memungkinkan untuk menulis kode tampak sinkron yang menggunakan fungsi asinkron dan kemudian akan berjalan secara asinkron di dalam fileFiber
.Kamu tidak bisa. Tidak mungkin untuk membuat kode asinkron sinkron. Anda perlu mengantisipasi hal itu dalam kode global Anda, dan menulisnya dengan gaya async dari awal. Apakah Anda membungkus kode global dalam fiber, menggunakan promise, generator promise, atau callback sederhana bergantung pada preferensi Anda.
Baik janji maupun serat dapat melakukannya.
sumber
fs
metode sinkron .Anda harus menggunakan janji:
Saya lebih suka definisi fungsi panah. Tetapi setiap string dalam bentuk "() => {...}" juga bisa ditulis sebagai "function () {...}"
Jadi topDog tidak asinkron meskipun memanggil fungsi asinkron.
EDIT: Saya menyadari banyak kali Anda perlu membungkus fungsi async di dalam fungsi sinkronisasi ada di dalam pengontrol. Untuk situasi tersebut, inilah trik pesta:
Memanfaatkan ini dengan callback, Anda dapat melakukan bungkus yang tidak menggunakan promise:
Dengan menerapkan trik ini ke EventEmitter, Anda bisa mendapatkan hasil yang sama. Tentukan pendengar EventEmitter di mana saya telah mendefinisikan callback, dan memancarkan peristiwa di mana saya memanggil callback.
sumber
Saya tidak dapat menemukan skenario yang tidak dapat diselesaikan dengan menggunakan node-fiber. Contoh yang Anda berikan menggunakan node-fibres berperilaku seperti yang diharapkan. Kuncinya adalah menjalankan semua kode yang relevan di dalam fiber, jadi Anda tidak perlu memulai fiber baru dalam posisi acak.
Mari kita lihat contoh: Katakanlah Anda menggunakan beberapa kerangka kerja, yang merupakan titik masuk aplikasi Anda (Anda tidak dapat memodifikasi kerangka kerja ini). Kerangka kerja ini memuat modul nodejs sebagai plugin, dan memanggil beberapa metode pada plugin. Katakanlah kerangka ini hanya menerima fungsi sinkron, dan tidak menggunakan serat dengan sendirinya.
Ada pustaka yang ingin Anda gunakan di salah satu plugin Anda, tetapi pustaka ini asinkron, dan Anda juga tidak ingin mengubahnya.
Utas utama tidak dapat dihasilkan saat tidak ada serat yang berjalan, tetapi Anda masih dapat membuat plugin menggunakan serat! Cukup buat entri pembungkus yang memulai seluruh kerangka di dalam fiber, sehingga Anda dapat menghasilkan eksekusi dari plugin.
Kelemahan: Jika kerangka menggunakan
setTimeout
atauPromise
s secara internal, maka itu akan keluar dari konteks serat. Hal ini dapat bekerja di sekitar dengan mengejeksetTimeout
,Promise.then
dan semua event handler.Jadi begitulah cara Anda menghasilkan serat sampai
Promise
terselesaikan. Kode ini mengambil fungsi async (Janji kembali) dan melanjutkan serat saat janji diselesaikan:framework-entry.js
async-lib.js
my-plugin.js
my-entry.js
Ketika Anda menjalankan
node framework-entry.js
itu akan melemparkan kesalahan:Error: yield() called with no fiber running
. Jika Anda menjalankannyanode my-entry.js
berfungsi seperti yang diharapkan.sumber
Membuat sinkronisasi kode Node.js sangat penting dalam beberapa aspek seperti database. Tetapi keuntungan sebenarnya dari Node.js terletak pada kode async. Karena ini adalah utas tunggal yang tidak memblokir.
kita bisa menyinkronkannya menggunakan fungsionalitas penting Fiber () Gunakan await () dan defer () kita memanggil semua metode menggunakan await (). kemudian ganti fungsi callback dengan defer ().
Kode Async normal. Ini menggunakan fungsi CallBack.
Sinkronkan kode di atas menggunakan Fiber (), await (), dan defer ()
Saya harap ini akan membantu. Terima kasih
sumber
Pola generator saat ini dapat menjadi solusi dalam berbagai situasi.
Berikut contoh perintah konsol sekuensial di nodejs menggunakan fungsi readline.question async:
sumber
Anda tidak boleh melihat apa yang terjadi di sekitar panggilan yang menciptakan serat, tetapi lebih pada apa yang terjadi di dalam serat. Setelah Anda berada di dalam fiber, Anda dapat memprogram dengan gaya sinkronisasi. Sebagai contoh:
Di dalam serat yang Anda panggil
f1
,f2
dansleep
seolah-olah mereka sinkron.Dalam aplikasi web biasa, Anda akan membuat Fiber di dispatcher permintaan HTTP Anda. Setelah Anda selesai melakukannya, Anda dapat menulis semua logika penanganan permintaan Anda dalam gaya sinkronisasi, meskipun itu memanggil fungsi async (fs, database, dll.).
sumber
while(true) handleNextRequest()
loop. Membungkus setiap penangan permintaan dalam serat akan.Saya kesulitan dengan ini pada awalnya dengan node.js dan async.js adalah perpustakaan terbaik yang saya temukan untuk membantu Anda menangani ini. Jika Anda ingin menulis kode sinkron dengan node, pendekatannya adalah dengan cara ini.
program ini akan SELALU menghasilkan ...
sumber
async
berfungsi dalam contoh Anda b / c itumain
, yang tidak peduli dengan pemanggil. Bayangkan semua kode Anda dibungkus dalam sebuah fungsi yang seharusnya mengembalikan hasil dari salah satu panggilan fungsi asinkron Anda. Ini dapat dengan mudah dibuktikan tidak berfungsi dengan menambahkanconsole.log('return');
di akhir kode Anda. Dalam kasus seperti itu, keluaranreturn
akan terjadi setelahin main
tetapi sebelumnyastep 1
.Javascript adalah bahasa utas tunggal, Anda tidak ingin memblokir seluruh server Anda! Kode Async menghilangkan kondisi balapan dengan membuat dependensi menjadi eksplisit.
Belajar mencintai kode asinkron!
Lihat
promises
kode asinkron tanpa membuat piramida neraka panggilan balik. Saya merekomendasikan pustaka promiseQ untuk node.jshttp://howtonode.org/promises
EDIT: sejauh ini ini adalah jawaban saya yang paling kontroversial, node sekarang memiliki kata kunci hasil, yang memungkinkan Anda untuk memperlakukan kode asinkron seolah-olah itu sinkron. http://blog.alexmaccaw.com/how-yield-will-transform-node
sumber