Saya memiliki fungsi sederhana yang terlihat seperti ini:
function(query) {
myApi.exec('SomeCommand', function(response) {
return response;
});
}
Pada dasarnya saya ingin menelepon myApi.exec
, dan mengembalikan respons yang diberikan dalam lambda callback. Namun, kode di atas tidak berfungsi dan langsung kembali segera.
Hanya untuk upaya yang sangat kejam, saya mencoba di bawah ini yang tidak berhasil, tetapi setidaknya Anda mendapatkan ide apa yang saya coba capai:
function(query) {
var r;
myApi.exec('SomeCommand', function(response) {
r = response;
});
while (!r) {}
return r;
}
Pada dasarnya, apa yang baik dari 'node.js / event driven' dalam hal ini? Saya ingin fungsi saya menunggu sampai panggilan balik dipanggil, lalu mengembalikan nilai yang diteruskan ke sana.
Jawaban:
Cara "node.js / event driven" yang baik untuk melakukan ini adalah tidak menunggu .
Seperti hampir semua hal lain ketika bekerja dengan sistem yang digerakkan oleh peristiwa seperti node, fungsi Anda harus menerima parameter panggilan balik yang akan dipanggil saat perhitungan selesai. Penelepon tidak boleh menunggu sampai nilai "dikembalikan" dalam arti normal, tetapi mengirim rutin yang akan menangani nilai yang dihasilkan:
Jadi Anda tidak menggunakannya seperti ini:
Tapi seperti ini:
sumber
fs
sync*
metode). Karena itu, saya pikir ini masih pertanyaan yang valid. Apakah ada cara yang bagus untuk mencapai pemblokiran di simpul selain dari kesibukan menunggu?sync
dilakukan metode. (2) Gunakan serat, github.com/laverdet/node-fibers , (3) Gunakan janji-janji, misalnya perpustakaan-Q, (4) Gunakan lapisan tipis di atas javascript, yang terlihat memblokir, tetapi kompilasi ke async, seperti maxtaco.github.com/coffee-scriptSalah satu cara untuk mencapai ini adalah dengan membungkus panggilan API menjadi janji dan kemudian gunakan
await
untuk menunggu hasilnya.Keluaran:
sumber
async/await
Saya tidak sering membutuhkan ini, jadi mengalami kesulitan mengingat bagaimana menangani situasi ini, saya menyalin ini untuk catatan / referensi pribadi saya.periksa ini: https://github.com/luciotato/waitfor-ES6
kode Anda dengan wait.for: (memerlukan generator, --harmony flag)
sumber
Jika Anda tidak ingin menggunakan panggilan balik maka Anda dapat menggunakan modul "Q".
Sebagai contoh:
Untuk informasi lebih lanjut lihat ini: https://github.com/kriskowal/q
sumber
Jika Anda menginginkannya sangat sederhana dan mudah, tanpa pustaka mewah, untuk menunggu fungsi callback dieksekusi dalam node, sebelum mengeksekusi beberapa kode lain, seperti ini:
sumber
Catatan: Jawaban ini mungkin sebaiknya tidak digunakan dalam kode produksi. Ini hack dan Anda harus tahu tentang implikasinya.
Ada modul uvrun (diperbarui untuk versi Nodejs yang lebih baru di sini ) di mana Anda dapat mengeksekusi satu putaran putaran libuv loop peristiwa utama (yang merupakan loop utama Nodejs).
Kode Anda akan terlihat seperti ini:
(Anda mungkin menggunakan alternatif
uvrun.runNoWait()
. Itu bisa menghindari beberapa masalah dengan pemblokiran, tetapi membutuhkan CPU 100%.)Perhatikan bahwa pendekatan semacam ini membatalkan seluruh tujuan Nodejs, yaitu memiliki segala sesuatu yang async dan non-blocking. Selain itu, ini bisa meningkatkan kedalaman callstack Anda, sehingga Anda mungkin berakhir dengan stack overflow. Jika Anda menjalankan fungsi tersebut secara rekursif, Anda pasti akan mengalami masalah.
Lihat jawaban lain tentang cara mendesain ulang kode Anda untuk melakukannya "benar".
Solusi ini di sini mungkin hanya berguna ketika Anda melakukan pengujian dan esp. ingin disinkronkan dan kode seri.
sumber
Karena node 4.8.0 Anda dapat menggunakan fitur ES6 yang disebut generator. Anda dapat mengikuti artikel ini untuk konsep yang lebih dalam. Tetapi pada dasarnya Anda dapat menggunakan generator dan janji untuk menyelesaikan pekerjaan ini. Saya menggunakan bluebird untuk menjanjikan dan mengelola generator.
Kode Anda harus baik seperti contoh di bawah ini.
sumber
seandainya Anda memiliki fungsi:
Anda dapat memanfaatkan panggilan balik seperti ini:
sumber
Itu mengalahkan tujuan non-blocking IO - Anda memblokirnya saat tidak perlu diblokir
:)
Anda harus membuat sarang panggilan balik Anda alih-alih memaksa node.js menunggu, atau menelepon panggilan balik lain di dalam panggilan balik di mana Anda memerlukan hasil
r
.Kemungkinannya adalah, jika Anda perlu memaksa pemblokiran, Anda berpikir bahwa arsitektur Anda salah.
sumber
http.get()
beberapa URL danconsole.log()
isinya. Mengapa saya harus melompat mundur untuk melakukannya di Node?Menggunakan async dan menunggu itu jauh lebih mudah.
sumber