Senkron ve asenkron programlama arasındaki fark nedir (node.js'de)


189

Düğümbaşını okuyordum ve aşağıdaki iki kod parçasına rastladım.

İlki:

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

İkinci olan:

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

Yapmaları gerekeni alıyorum, sorgunun cevabını almak için veritabanını sorguluyorlar. Ve sonra console.log('Hello world').

Birincisi sözde senkron kod. İkincisi asenkron kod.

İki parça arasındaki fark benim için çok belirsiz. Çıktı ne olurdu?

Eşzamansız programlamada çalışmak da bana yardımcı olmadı.


41
Google ile hiçbir şey bulamadığınız için Stange, bu oldukça büyük bir konu. Eşzamanlı programlamada, her adım bir öncekinin yürütülmesi bittikten sonra gerçekleştirilir. Zaman uyumsuz olarak, 1. adım tamamlanmamış olsa bile 2. adım gerçekleştirilir. İkinci örneğinizde tanımladığınız işleve callBack işlevi adı verilir ve veritabanından sonuç döndürülür döndürülmez çalıştırılır; bu da muhtemelen console.log çalıştırıldıktan sonra gerçekleşir.
Laurent S.

7
@Bartdude Eşzamansız programlama konusunda çok şey vardı, ancak bunun ne olduğu ve pratikte ne anlama geldiği hakkında basit bir açıklama yoktu.
Azeirah

1
@GabrielLlamas Senkron işlevlerden neden kaçınmalıyız?
Charlie Parker

3
@CharlieParker Çünkü olay döngüsünü engelliyorlar ve eşzamansız olaylı bir G / Ç modelinin tüm avantajlarını kaybediyorsunuz. Çünkü kötü bir uygulama. Şöyle düşünün: Eşzamansız işlevler kullanmıyorsanız, neden Node.js kullanıyorsunuz?
Gabriel Llamas

1
@GabrielLlamas, bir INSERT sorgusu yürütüyorum ve sonra son eklenen kimliği kullanmak istiyorum database.query(), o zaman ben senkronize olarak çağırmak gerekir, değil mi? ya da yaklaşım ne olmalı? (Bu soru uzun süredir var)
San

Yanıtlar:


225

Fark, ilk örnekte , programın ilk satırda engellenmesidir. Bir sonraki satırın ( console.log) beklemesi gerekecek.

Olarak ikinci örnekte , console.logsorgu işlenirken çalıştırılacaktır. Yani, programınız başka şeyler yaparken sorgu arka planda işlenir ve sorgu verileri hazır olduğunda, bununla ne isterseniz yaparsınız.

Yani, kısaca: İlk örnek bloke olurken, ikinci örnek bloke olmayacak.

Aşağıdaki iki örneğin çıktısı:

// 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");

Olabilir:

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

Not
Düğümün kendisi tek iş parçacıklı olsa da, paralel olarak çalışabilecek bazı görevler vardır. Örneğin, Dosya Sistemi işlemleri farklı bir işlemde gerçekleşir.

Bu nedenle Düğüm zaman uyumsuz işlemler yapabilir: bir iş parçacığı dosya sistemi işlemleri yaparken, ana Düğüm iş parçacığı javascript kodunuzu yürütmeye devam eder. Düğüm gibi olay güdümlü bir sunucuda, dosya sistemi iş parçacığı, o düğümle ilişkili herhangi bir veriyle (veritabanı sorgusu veya hata gibi) tamamlanma, hata veya ilerleme gibi belirli olayların ana Düğüm iş parçacığını bilgilendirir ana Düğüm iş parçacığı bu verilerle ne yapılacağına karar verir.

Bununla ilgili daha fazla bilgiyi buradan edinebilirsiniz: Node.js'de tek iş parçacıklı engellemeyen G / Ç modeli nasıl çalışır?


9
Temelde, ilk kod parçasını yürüttüğünüzde, böyle bir şey yapacak request query.; 5 seconds later when the request is done; console.log:; ikincisi çalıştığında request query; console.log; work on the query:;
Azeirah

1
@JohnGalt sql farklı bir iş parçacığında çalışır. Ama tabii ki bu kullandığınız sql sürücüsünün uygulanmasına bağlıdır. Sürücü yeni bir iş parçacığı oluşturmalı, mysql'e bağlanmalı ve sorguyu çalıştırmalıdır. Bittiğinde, sonucu olay kuyruğuna gönderin, Düğüm geri aramayı çağırır.
Salvatorelab

4
Eşzamansız örneğin # 1 ile aynı şeyi vermesi mümkün değil mi? Mesela, database.queryo kadar hızlı bitiyor ki , ulaştığımız console.logzaman görev zaten yapılıyor.
greatwolf

2
@ console.log("Next line");Örnek 2'de anonim işlevin içinde console.log("query finished");olsaydı, hemen ardından , "Sonraki Satır" "sorgu tamamlandıktan" SONRA yazdırılır anlamına gelir mi? Yani, her şeyi iç içe bir şekilde yerleştirirsem, her şey eşzamanlı olarak çalışırdı, bu nedenle belirli işlevlerin eşzamanlı sürümlerini kullanma konusunda endişelenmem gerekmeyecekti. Anladığım kadarıyla doğru muyum?
Abdul

4
Kısa cevap : Evet @Abdul, haklısın. Uzun cevap : Yuvalama işlevleri (geri aramalar), işleri birbiri ardına, "birbiri ardına" yapmanın yoludur. Ancak bu teknik olarak "eşzamanlı" değildir. Anonim işlev yine de "engelleme işlemi tamamlandığında" veya başka bir deyişle "eşzamansız olarak" yürütülür. Bu engelleme işlemi gerçekleştirilirken Node.js başka işlevleri de yürütebilir. Fonksiyonlar async olarak kalır, sadece onları zincirlersiniz. Senkronizasyon fonksiyonları yürütmeyi engeller, işte anahtar budur.
Salvatorelab

75

Bu iki yaklaşım arasındaki fark aşağıdaki gibidir:

Senkron yol: Her işlemin tamamlanmasını bekler, bundan sonra yalnızca bir sonraki işlemi yürütür. Sorgunuz için: console.log()Sorgu, Veritabanından tüm sonucu almak için yürütmeyi bitirene kadar & komutları yürütülmez.

Asenkron yol: Her işlemin tamamlanmasını asla beklemez, bunun yerine tüm işlemleri yalnızca ilk GO'da yürütür. Her işlemin sonucu, sonuç elde edildiğinde ele alınacaktır. Sorgunuz için: console.log()Komut Database.Query()yöntemden hemen sonra yürütülür . Veritabanı sorgusu arka planda çalışırken ve veri alma işlemi bittiğinde sonucu yüklerken.

Kullanım örnekleri

  1. İşlemleriniz DB'den büyük verileri sorgulamak gibi çok ağır kaldırma yapmıyorsa, Eşzamanlı yolla devam edin aksi halde Asenkron yolla.

  2. Zaman uyumsuz bir şekilde kullanıcıya bazı İlerleme göstergeleri gösterebilirken, arka planda ağır çalışmalarınıza devam edebilirsiniz. Bu, GUI uygulamaları için ideal bir senaryodur.


2
Bu, db.query'nin (cmd, geri arama) aynı anda çalıştığı anlamına mı geliyor (iş parçacıklarında olduğu gibi)? Aynı anda mı çalışıyorlar?
Charlie Parker

İkinci örneğinde, sorgunun o kadar hızlı bitmesi, daha önce önce geri aramayı çağırması ihtimali var console.logmı?
Fahmi

@Fahmi teorik olarak evet, neredeyse imkansız
Leo Messi

24

Her iki örneğe de bir satır eklerseniz bu biraz daha açık hale gelir:

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

İkinci olan:

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

Bunları çalıştırmayı deneyin ve ilk (senkron) örneğin, example.length değerinin 'Merhaba Dünya' satırından ÖNCE yazdırılacağını göreceksiniz. İkinci (eşzamansız) örnekte, sonuç. Uzunluğu (büyük olasılıkla) "Merhaba Dünya" satırından SONRA yazdırılır.

Çünkü ikinci örnekte, database.queryarka planda eşzamansız olarak çalıştırılır ve komut dosyası "Merhaba Dünya" ile hemen devam eder. console.log(result.length)Veritabanı sorgusu tamamlandığında sadece yürütülür.


1
diyorsunuz: sonuç. uzunluk (büyük olasılıkla) "Merhaba Dünya" satırından SONRA yazdırılacaktır. .... neden sadece "büyük olasılıkla" olur? Her zaman console.log çıktısından sonra yazdırıldığını düşünüyorum. Açıklama için teşekkürler :)
humanityANDpeace

9
@humanityANDpeace: eşzamansız erişimin tamamı budur: ne zaman yapılacağını bilmiyorsunuz . Belki de saçma bir hızlı veritabanıdır ve Javascript "Merhaba Dünya" satırına ulaşmadan önce veritabanı sorgusu geri döner ...
Martijn

19

İlk olarak, bu soruya cevap vermekte geciktiğimin farkındayım.

Senkron ve asenkron tartışmadan önce, programların nasıl çalıştığına kısaca göz atalım.

In senkron durumda, her bir deyim tamamlar sonraki deyimi çalıştırılır önce. Bu durumda program ifadelerin sıralamasına göre tam olarak değerlendirilir.

Bu nasıl asenkron JavaScript çalışır. JavaScript motorunda iki bölüm vardır; bunlardan biri koda bakar ve işlemleri sıralar, diğeri kuyruğu işler. Kuyruk işleme bir iş parçacığında gerçekleşir, bu nedenle bir seferde yalnızca bir işlem olabilir.

Eşzamansız bir işlem (ikinci veritabanı sorgusu gibi) görüldüğünde, kod ayrıştırılır ve işlem kuyruğa alınır, ancak bu durumda bu işlem tamamlandığında çalıştırılacak bir geri arama kaydedilir. Kuyrukta zaten birçok işlem olabilir. Sıranın önündeki işlem işlenir ve kuyruktan kaldırılır. Veritabanı sorgusu işlemi işlendikten sonra, istek veritabanına gönderilir ve tamamlandığında geri arama tamamlandığında yürütülür. Şu anda, işlemi "işleyen" kuyruk işlemcisi bir sonraki işlemde hareket eder - bu durumda

    console.log("Hello World"); 

Veritabanı sorgusu hala işleniyor, ancak console.log işlemi kuyruğun önünde ve işleniyor. Bu eşzamanlı bir işlem olarak hemen "Hello World" çıktısına neden olur. Bir süre sonra, veritabanı işlemi tamamlanır, ancak o zaman sorgu ile kaydedilen geri arama çağrılır ve işlenir ve değişken sonucun değeri satırlara ayarlanır.

Bir eşzamansız işlemin başka bir eşzamansız işlemle sonuçlanması mümkündür, bu ikinci işlem kuyruğa konur ve kuyruğun önüne geldiğinde işlenir. Zaman uyumsuz bir işlemle kaydedilen geri aramayı çağırmak, JavaScript çalışma süresinin tamamlandığında işlemin sonucunu nasıl döndürdüğüdür.

Hangi JavaScript işleminin eşzamansız olduğunu bilmenin basit bir yöntemi, geri arama gerektirip gerektirmediğini not etmektir - geri arama, ilk işlem tamamlandığında yürütülecek koddur. Sorudaki iki örnekte, sadece ikinci vakanın bir geri çağırma olduğunu görebiliriz, bu yüzden ikisinin asenkron çalışmasıdır. Eşzamansız bir işlemin sonucunu ele alma farklı stilleri nedeniyle her zaman böyle değildir.

Daha fazla bilgi edinmek için vaatleri okuyun. Vaatler, eşzamansız bir işlemin sonucunun ele alınmasının başka bir yoludur. Vaatlerle ilgili güzel şey, kodlama stilinin daha çok senkron kod gibi hissetmesidir.

'Fs' düğümü gibi birçok kütüphane, bazı işlemler için hem eşzamanlı hem de eşzamansız stiller sağlar. İşlemin uzun sürmediği ve çok kullanılmadığı durumlarda - bir yapılandırma dosyasının okunması durumunda - senkronize stil işlemi, okunması daha kolay olan kodla sonuçlanır.


6

Senkronize durumda, SQL sorgusunun yürütülmesi bitene kadar console.log komutu yürütülmez.

Eşzamansız durumda, console.log komutu doğrudan yürütülür. Sorgunun sonucu daha sonra "geri arama" işlevi tarafından saklanır.


1
Ama aslında aynı anda mı çağrılıyor? Beni şaşırtan şey, asenkron kodda, gerçek kodun aynı anda paralel olarak çalıştırılması mı?
Charlie Parker

Bu işlemciye (çok çekirdekli mi?) Ve işletim sistemine bağlıdır. Bkz. En.wikipedia.org/wiki/Multithreading_(software)#Multithreading
ilgili

4

Temel fark asenkron programlamada, aksi takdirde yürütmeyi durdurmazsınız. 'İstek' yapılırken diğer kodları yürütmeye devam edebilirsiniz.


2

İşlev, ikincisini eşzamansız yapar.

Birincisi, programı bir sonraki satırın devam etmeden önce her satırın çalışmasını bitirmesini beklemeye zorlar. İkincisi, her satırın aynı anda (ve bağımsız olarak) birlikte çalışmasına izin verir.

Eşzamansız veya eşzamanlılığa izin veren diller ve çerçeveler (js, node.js), gerçek zamanlı aktarım gerektiren şeyler için mükemmeldir (örn. Sohbet, stok uygulamaları).


0

Senkronizasyon Programlama

C, C #, Java gibi programlama dilleri senkron programlamadır, böylece yazdıklarınız yazma sırasına göre yürütülür.

-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

zaman uyumsuz

NodeJ'ler async özelliği ile gelir, doğada tıkanmaz, zaman alan herhangi bir G / Ç görevinde (getirme, yazma, okuma), nodejs boşta kalmaz ve görevin bitmesini beklemez, ' sıradaki sonraki görevleri yürütmeye başlayacaktır ve o zaman görev alma işlemi tamamlandığında geri arama kullanarak bildirim verecektir. Aşağıdaki örnek yardımcı olacaktır:

//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();

Kısacası, Çıktı şu şekildedir:

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

Eşitlemenin kesinlikle 600 (500 + 100 + işlem süresi) milisaniyeden fazla süreceği fark açıktır, asenkron zaman kazandırır.


0

Senkron işlevler engellenirken, senkronize olmayan işlevler kilitlenmez. Eşzamanlı işlevlerde, ifadeler sonraki ifadenin çalıştırılmasından önce tamamlanır. Bu durumda, program ifadelerin sırasına göre tam olarak değerlendirilir ve ifadelerden birinin çok uzun sürmesi durumunda programın yürütülmesi duraklatılır.

Eşzamansız işlevler genellikle geri çağrıyı parametre olarak kabul eder ve eşzamansız işlev çağrıldıktan hemen sonra yürütme sonraki satırda devam eder. Geri arama yalnızca eşzamansız işlem tamamlandığında ve çağrı yığını boş olduğunda çağrılır. Bir web sunucusundan veri yükleme veya bir veritabanını sorgulama gibi ağır hizmet işlemleri, ana iş parçacığının, bu uzun işlem tamamlanıncaya kadar (tarayıcılarda kullanıcı arayüzü donacak) bloke etmek yerine diğer işlemleri yürütmeye devam edebilmesi için eşzamansız olarak yapılmalıdır. .

Orginal Yayınlanan Github: Bağlantı


0

JS'de eşzamansız programlama:

Senkron

  • Bu yapılana kadar başka kodların yürütülmesini durdurur.
  • Bu daha fazla yürütmenin durdurulması nedeniyle, eşzamanlı kod 'engelleme' olarak adlandırılır. Başka hiçbir kod yürütülmeyecek şekilde engelleme.

eşzamanlı olmayan

  • Bunun yürütülmesi olay döngüsüne ertelenir, bu bir JS sanal makinesinde eşzamansız işlevleri yürüten bir yapıdır (eşzamanlı işlevler yığını boş olduktan sonra).
  • Eşzamansız kod, başka kodun çalışmasını engellemediğinden engellemesiz olarak adlandırılır.

Misal:

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

log(1);

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

log(3)

  • Örnek 1, 3, 2'yi kaydeder.
  • 2, yığın boş olduktan sonra yürütülen eşzamansız bir işlevin içinde olduğu için en son günlüğe kaydedilir.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.