Apa perbedaan antara pemrograman sinkron dan asinkron (dalam node.js)


189

Saya telah membaca nodebeginner Dan saya menemukan dua bagian kode berikut.

Yang pertama:

    var result = database.query("SELECT * FROM hugetable");
    console.log("Hello World");

Yang kedua:

    database.query("SELECT * FROM hugetable", function(rows) {
       var result = rows;
    });
    console.log("Hello World");

Saya mendapatkan apa yang seharusnya mereka lakukan, mereka meminta basis data untuk mengambil jawaban atas permintaan. Dan kemudian console.log('Hello world').

Yang pertama seharusnya kode sinkron. Dan yang kedua adalah kode asinkron.

Perbedaan antara keduanya sangat samar bagi saya. Apa yang akan menjadi output?

Googling pada pemrograman asinkron juga tidak membantu saya.


41
Aneh, Anda tidak menemukan apa pun dengan google, ini topik yang agak besar. Dalam pemrograman sinkron, setiap langkah dilakukan satu setelah yang sebelumnya selesai dijalankan. Dalam asynchroneous, langkah 2 akan dilakukan bahkan jika langkah 1 belum selesai. Fungsi yang Anda lihat didefinisikan dalam contoh kedua Anda disebut fungsi callBack, dan akan dijalankan segera setelah hasil dari database akan dikembalikan, yang mungkin akan setelah konsol.log dijalankan.
Laurent S.

7
@ Bartdude Ada banyak hal tentang pemrograman asinkron, tetapi tidak ada penjelasan yang sederhana tentang apa itu, dan apa artinya dalam praktik.
Azeirah

1
@GabrielLlamas Mengapa kita harus menghindari fungsi sinkron?
Charlie Parker

3
@CharlieParker Karena mereka memblokir loop acara dan Anda kehilangan semua manfaat dari model I / O yang tidak sinkron. Dan karena itu praktik yang buruk. Pikirkan seperti ini: Jika Anda tidak menggunakan fungsi asinkron, mengapa Anda menggunakan Node.js?
Gabriel Llamas

1
@GabrielLlamas, jika saya menjalankan kueri INSERT dan saya ingin menggunakan ID yang dimasukkan setelahnya database.query(), maka saya harus menyebutnya sebagai sinkron, bukan? atau apa yang harus menjadi pendekatan? (Pertanyaan ini sudah lama saya miliki)
San

Jawaban:


225

Perbedaannya adalah bahwa pada contoh pertama , program akan memblokir di baris pertama. Baris berikutnya ( console.log) harus menunggu.

Dalam contoh kedua , console.logakan dieksekusi SAAT permintaan sedang diproses. Artinya, kueri akan diproses di latar belakang, sementara program Anda melakukan hal-hal lain, dan setelah data kueri siap, Anda akan melakukan apa pun yang Anda inginkan dengannya.

Jadi, singkatnya: Contoh pertama akan memblokir, sedangkan yang kedua tidak.

Output dari dua contoh berikut:

// Example 1 - Synchronous (blocks)
var result = database.query("SELECT * FROM hugetable");
console.log("Query finished");
console.log("Next line");


// Example 2 - Asynchronous (doesn't block) 
database.query("SELECT * FROM hugetable", function(result) {
    console.log("Query finished");
});
console.log("Next line");

Akan menjadi:

  1. Query finished
    Next line
  2. Next line
    Query finished

Catatan
Meskipun Node itu sendiri berulir tunggal , ada beberapa tugas yang dapat berjalan secara paralel. Misalnya, operasi Sistem File terjadi dalam proses yang berbeda.

Itu sebabnya Node dapat melakukan operasi async: satu utas sedang melakukan operasi sistem file, sedangkan utas utama terus mengeksekusi kode javascript Anda. Di server yang digerakkan oleh peristiwa seperti Node, utas sistem file memberi tahu utas Node utama pada peristiwa tertentu seperti penyelesaian, kegagalan, atau kemajuan, bersama dengan data apa pun yang terkait dengan peristiwa itu (seperti hasil kueri basis data atau kesalahan pesan) dan utas Node utama memutuskan apa yang harus dilakukan dengan data itu.

Anda dapat membaca lebih lanjut tentang ini di sini: Bagaimana model IO non-blocking tunggal bekerja di Node.js


9
Jadi pada dasarnya, ketika saya mengeksekusi potongan kode pertama, ia akan melakukan sesuatu seperti ini request query.; 5 seconds later when the request is done; console.log:; ketika kedua mengeksekusi: request query; console.log; work on the query;
Azeirah

1
@JohnGalt sql berjalan di utas yang berbeda. Tapi tentu saja itu tergantung pada implementasi driver sql yang Anda gunakan. Pengemudi harus menelurkan utas baru, sambungkan ke mysql dan jalankan kueri. Setelah selesai, posting hasilnya ke antrian acara , dan Node akan memanggil panggilan balik.
Salvatorelab

4
Apakah tidak mungkin bagi contoh async untuk menampilkan hal yang sama dengan # 1? Seperti misalnya, database.queryselesai begitu cepat sehingga pada saat kita mencapai console.logtugas sudah selesai.
greatwolf

2
@TheBronx jika console.log("Next line");dalam contoh 2 ada di dalam fungsi anonim, jadi setelah itu console.log("query finished");, itu berarti "Baris Berikutnya" akan dicetak SETELAH "permintaan selesai" kan? Jadi, jika saya memiliki semuanya dengan cara bersarang, semuanya akan berjalan secara sinkron, maka saya tidak perlu khawatir tentang menggunakan versi sinkron dari fungsi-fungsi tertentu. Apakah saya benar dalam pengertian saya?
Abdul

4
Jawaban singkat : Ya @ Abdul, Anda benar. Jawaban panjang : Fungsi bersarang (panggilan balik) adalah cara untuk melakukan berbagai hal secara berurutan, "satu demi satu". Tapi itu tidak "sinkron" secara teknis. Fungsi anonim masih dieksekusi "ketika operasi pemblokiran telah selesai", atau dengan kata lain, "asinkron". Node.js dapat menjalankan fungsi lain saat operasi pemblokiran sedang berlangsung. Fungsi tetap asink, hanya saja Anda merantai mereka. Sinkronisasi fungsi memblokir eksekusi, itulah kuncinya.
Salvatorelab

75

Perbedaan antara kedua pendekatan ini adalah sebagai berikut:

Cara sinkron: Menunggu setiap operasi untuk menyelesaikan, setelah itu hanya menjalankan operasi berikutnya. Untuk kueri Anda: console.log()Perintah tidak akan dieksekusi sampai & kecuali kueri telah selesai dieksekusi untuk mendapatkan semua hasil dari Database.

Cara asinkron: Tidak pernah menunggu setiap operasi untuk menyelesaikan, melainkan menjalankan semua operasi di GO pertama saja. Hasil dari setiap operasi akan ditangani setelah hasilnya tersedia. Untuk kueri Anda: console.log()Perintah akan dieksekusi segera setelah Database.Query()metode. Sementara kueri Database berjalan di latar belakang dan memuat hasilnya setelah selesai mengambil data.

Gunakan kasing

  1. Jika operasi Anda tidak melakukan pengangkatan yang sangat berat seperti meminta data besar dari DB kemudian lanjutkan dengan cara Sinkron atau cara Asinkron.

  2. Dengan cara Asinkron Anda dapat menampilkan beberapa indikator Kemajuan kepada pengguna sementara di latar belakang Anda dapat melanjutkan pekerjaan berat Anda. Ini adalah skenario ideal untuk aplikasi GUI.


2
Apakah itu berarti bahwa db.query (cmd, callback) berjalan bersamaan (seperti pada utas)? Apakah mereka berjalan pada saat yang sama?
Charlie Parker

Dalam contoh kedua, apakah ada kemungkinan kueri selesai begitu cepat sehingga panggilan balik terlebih dahulu, sebelumnya console.log?
Fahmi

@Fahmi secara teoritis ya, praktis sangat tidak mungkin
Leo Messi

24

Ini akan menjadi sedikit lebih jelas jika Anda menambahkan baris ke kedua contoh:

var result = database.query("SELECT * FROM hugetable");
console.log(result.length);
console.log("Hello World");

Yang kedua:

database.query("SELECT * FROM hugetable", function(rows) {
   var result = rows;
   console.log(result.length);
});
console.log("Hello World");

Coba jalankan ini, dan Anda akan melihat bahwa contoh pertama (sinkron), result.length akan dicetak SEBELUM garis 'Hello World'. Dalam contoh kedua (asinkron), panjang result.length akan (kemungkinan besar) akan dicetak SETELAH garis "Hello World".

Itu karena dalam contoh kedua, database.querydijalankan secara tidak sinkron di latar belakang, dan skrip berlanjut langsung dengan "Hello World". Ini console.log(result.length)hanya dieksekusi ketika permintaan basis data telah selesai.


1
Anda mengatakan: result.length akan (kemungkinan besar) akan dicetak SETELAH garis "Hello World". .... mengapa itu hanya "kemungkinan besar"? Saya pikir itu selalu dicetak setelah keluaran console.log. Terima kasih atas klarifikasi :)
humanityANDpeace

9
@ humanityANDpeace: itulah inti dari akses asinkron: Anda tidak tahu kapan itu akan dilakukan. Mungkin ini adalah basis data yang sangat cepat, dan permintaan basis data kembali bahkan sebelum Javascript sampai ke baris "Hello World" ...
Martijn

19

Pertama, saya sadar saya terlambat menjawab pertanyaan ini.

Sebelum membahas tentang sinkron dan asinkron, mari kita lihat secara singkat bagaimana program berjalan.

Dalam kasus sinkron , setiap pernyataan selesai sebelum pernyataan berikutnya dijalankan. Dalam hal ini program dievaluasi sesuai dengan urutan pernyataan.

Ini adalah cara kerja asinkron dalam JavaScript. Ada dua bagian dalam mesin JavaScript, satu bagian yang melihat kode dan operasi enqueues dan lainnya yang memproses antrian. Pemrosesan antrian terjadi dalam satu utas, itulah sebabnya mengapa hanya satu operasi yang dapat terjadi sekaligus.

Ketika operasi asinkron (seperti permintaan basis data kedua) terlihat, kode diuraikan dan operasi dimasukkan dalam antrian, tetapi dalam hal ini panggilan balik terdaftar untuk dijalankan ketika operasi ini selesai. Antrian mungkin sudah memiliki banyak operasi di dalamnya. Operasi di depan antrian diproses dan dihapus dari antrian. Setelah operasi untuk permintaan basis data diproses, permintaan dikirim ke basis data dan ketika selesai, panggilan balik akan dieksekusi setelah selesai. Pada saat ini, prosesor antrian yang telah "menangani" operasi bergerak pada operasi berikutnya - dalam hal ini

    console.log("Hello World"); 

Permintaan basis data masih diproses, tetapi operasi console.log ada di depan antrian dan diproses. Ini menjadi operasi yang sinkron dijalankan segera menghasilkan output "Hello World". Beberapa waktu kemudian, operasi database selesai, hanya kemudian panggilan balik yang terdaftar dengan permintaan dipanggil dan diproses, mengatur nilai hasil variabel ke baris.

Ada kemungkinan bahwa satu operasi asinkron akan menghasilkan operasi asinkron lain, operasi kedua ini akan dimasukkan ke dalam antrian dan ketika sampai di depan antrian akan diproses. Memanggil panggilan balik yang terdaftar dengan operasi asinkron adalah cara JavaScript run time mengembalikan hasil operasi ketika selesai.

Metode sederhana untuk mengetahui operasi JavaScript mana yang tidak sinkron adalah untuk mencatat jika membutuhkan panggilan balik - panggilan balik adalah kode yang akan dieksekusi ketika operasi pertama selesai. Dalam dua contoh dalam pertanyaan, kita hanya dapat melihat kasus kedua memiliki panggilan balik, jadi ini adalah operasi asinkron dari keduanya. Ini tidak selalu terjadi karena berbagai gaya penanganan hasil operasi asinkron.

Untuk mempelajari lebih lanjut, baca tentang janji. Janji adalah cara lain di mana hasil dari operasi asinkron dapat ditangani. Yang menyenangkan tentang janji adalah bahwa gaya pengkodean terasa lebih seperti kode sinkron.

Banyak perpustakaan seperti simpul 'fs', menyediakan gaya sinkron dan asinkron untuk beberapa operasi. Dalam kasus di mana operasi tidak memakan waktu lama dan tidak banyak digunakan - seperti dalam kasus membaca file konfigurasi - operasi gaya sinkron akan menghasilkan kode yang lebih mudah dibaca.


6

Dalam kasus sinkron, perintah console.log tidak dieksekusi sampai permintaan SQL selesai dieksekusi.

Dalam kasus asinkron, perintah console.log akan langsung dieksekusi. Hasil kueri kemudian akan disimpan oleh fungsi "callback" beberapa saat setelahnya.


1
Tetapi apakah sebenarnya dipanggil secara bersamaan? Hal yang membingungkan saya adalah, dalam kode asinkron, apakah kode aktual dijalankan pada saat yang bersamaan secara paralel?
Charlie Parker

Ini tergantung pada prosesor (apakah itu multi-core?) Dan sistem operasinya. Lihat en.wikipedia.org/wiki/Multithreading_(software)#Multithreading
terkait

4

Perbedaan utama adalah dengan pemrograman asinkron, Anda tidak menghentikan eksekusi sebaliknya. Anda dapat terus mengeksekusi kode lain saat 'permintaan' sedang dibuat.


2

Fungsi ini membuat yang kedua tidak sinkron.

Yang pertama memaksa program untuk menunggu setiap baris untuk menyelesaikannya berjalan sebelum yang berikutnya dapat melanjutkan. Yang kedua memungkinkan setiap baris untuk berjalan bersama (dan secara mandiri) sekaligus.

Bahasa dan kerangka kerja (js, node.js) yang memungkinkan asinkron atau konkurensi sangat bagus untuk hal-hal yang memerlukan transmisi waktu nyata (mis. Obrolan, aplikasi stok).


0

Sinkronisasi Pemrograman

Bahasa pemrograman seperti C, C #, Java adalah program sinkronisasi, apa pun yang Anda tulis akan dieksekusi dalam urutan tulisan Anda.

-GET DATA FROM SQL.
//Suppose fetching data take 500 msec

-PERFORM SOME OTHER FUNCTION.
//Performing some function other will take 100 msec, but execution of other 
//task start only when fetching of sql data done (i.e some other function 
//can execute only after first in process job finishes).

-TOTAL TIME OF EXECUTION IS ALWAYS GREATER THAN (500 + 100 + processing time) 
msec

Async

NodeJs hadir dengan fitur async, sifatnya non-blocking, misalkan dalam tugas I / O yang membutuhkan waktu (mengambil, menulis, membaca), nodejs tidak akan diam dan menunggu tugas selesai, itu ' Saya akan mulai menjalankan tugas-tugas berikutnya dalam antrian, dan setiap kali tugas yang diselesaikan selesai, akan diberitahukan menggunakan panggilan balik. Contoh berikut akan membantu:

//Nodejs uses callback pattern to describe functions.
//Please read callback pattern to understand this example

//Suppose following function (I/O involved) took 500 msec
function timeConsumingFunction(params, callback){
  //GET DATA FROM SQL
  getDataFromSql(params, function(error, results){
    if(error){
      callback(error);
    }
    else{
      callback(null, results);
    }
  })
}

//Suppose following function is non-blocking and took 100 msec
function someOtherTask(){
  //some other task
  console.log('Some Task 1');
  console.log('Some Task 2');
}

console.log('Execution Start');

//Start With this function
timeConsumingFunction(params, function(error, results){
    if(error){
      console.log('Error')
    }
    else{
      console.log('Successfull'); 
    }
  })

//As (suppose) timeConsumingFunction took 500 msec, 
//As NodeJs is non-blocking, rather than remain idle for 500 msec, it will start 
//execute following function immediately
someOtherTask();

Singkatnya, Output adalah sebagai:

Execution Start
//Roughly after 105 msec (5 msec it'll take in processing)
Some Task 1
Some Task 2
//Roughly After 510 msec
Error/Successful //depends on success and failure of DB function execution

Perbedaannya jelas di mana sinkronisasi pasti akan membutuhkan lebih dari 600 (500 + 100 + waktu pemrosesan) msec, async menghemat waktu.


0

Fungsi sinkron memblokir sedangkan fungsi asinkron tidak. Dalam fungsi sinkron, pernyataan lengkap sebelum pernyataan berikutnya dijalankan. Dalam hal ini, program dievaluasi sesuai urutan pernyataan dan pelaksanaan program dijeda jika salah satu pernyataan memakan waktu sangat lama.

Fungsi asinkron biasanya menerima panggilan balik sebagai parameter dan eksekusi dilanjutkan pada baris berikutnya segera setelah fungsi asinkron dipanggil. Callback hanya dipanggil ketika operasi asinkron selesai dan tumpukan panggilan kosong. Operasi tugas berat seperti memuat data dari server web atau meminta basis data harus dilakukan secara tidak serempak sehingga utas utama dapat terus menjalankan operasi lain alih-alih memblokir hingga operasi yang lama selesai (dalam hal browser, UI akan membeku) .

Orginal Diposting di Github: Tautan


0

Pemrograman asinkron dalam JS:

Sinkronis

  • Hentikan eksekusi kode lebih lanjut sampai ini selesai.
  • Karena ini penghentian eksekusi lebih lanjut, kode sinkron disebut 'pemblokiran'. Memblokir dalam arti bahwa tidak ada kode lain yang akan dieksekusi.

Tidak sinkron

  • Eksekusi ini ditunda ke loop acara, ini adalah konstruksi di mesin virtual JS yang menjalankan fungsi asinkron (setelah tumpukan fungsi sinkron kosong).
  • Kode asinkron disebut non blocking karena tidak memblokir kode lebih lanjut dari berjalan.

Contoh:

// This function is synchronous
function log(arg) {
    console.log(arg)
}

log(1);

// This function is asynchronous
setTimeout(() => {
    console.log(2)
}, 0);

log(3)

  • Contohnya log 1, 3, 2.
  • 2 dicatat terakhir karena berada di dalam fungsi asinkron yang dijalankan setelah tumpukan kosong.
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.