main-post-cover

    JavaScript dövrlərində async/await ilə necə işləməli?

    Digər
    Code-News
    22.01.2019
    Farid Pardashunas

    #Step IT Academy tərəfindən təqdim olunur  





        JavaScript-də asinxron dövrləri necə növbə ilə və paralel başlatmaq olar? Asinxron magiyanı başlatmazdan öncə, mən, klassik sinxron dövrlərin necə göründüyünü yadınıza salmaq istəyirəm.

     Sinxron dövrlər
        Əvvəllər mən dövrləri belə yazırdım:
    for (var i=0; i < array.length; i++) {
      var item = array[i];
      // item ilə nəsə eləyirik
    }
    
        Bu dövr yaxşıdır və sürətlidir. Amma onun oxunma və dəstəklənmə ilə çoxlu problemləri var. Sonra mən onun daha yaxşı versiyasına keçdim:
    array.forEach((item) => {
       // item ilə nəsə eləyirik
    });
    

        JavaScript dili çox sürətlə inkişaf edir. Yeni-yeni özəlliklər və sinaktik dəyişikliklər ortaya çıxır. Ən sevdiyim dəyişikliklərdən biri async/await-dır. Hazırda mən bu sintaksı tez-tez istifadə edirəm Hərdən belə vəziyyətlər yaranır ki, mən orada massivin elementləri ilə asinxron işlər görməliyəm.
    Asinxron dövrlər
        Dövrün bədənində await necə istifadə olunmalıdır? Gəlin öncə sadəcə asinxron bir dövr yazıb, hər bir elementin emal olunmasını gözləyək:
     
    
    async function processArray(array) {
      array.forEach(item => {
        //burada biz anonim sinxron funksiyanı müəyyən etdik
        // AMMA BU KOD SƏHV ÇIXARACAQ!
        await func(item);
      })
    }
    

        Bu kod səhv çıxaracaq. Niyə? Çünki bir sinxron funksiyanın daxilində await istifadə edə bilmərik. Gördüyünüz kimi processArray - asinxron funksiyadır. Amma forEach üçün istifadə elədiyimiz anonim funksiya sinxrondur.
        Biz bununla necə işləyə bilərik? 
    1. Bitməsini gözləməyə bilərik
        Biz anonim funksiyanı asinxron kimi müəyyən edə bilərik:
    async function processArray(array) {
      array.forEach(async (item) => {
        await func(item);
      })
      console.log('Done!');
    }
    
        Lakin forEach tapşırığın bitməsini gözləməyəcək. forEach - sinxron əməliyyatdır. O sadəcə tapşırıqları işə salıb öz yoluna davam edəcək. Bəsit bir test ilə yoxlayaq:
    function delay() {
      return new Promise(resolve => setTimeout(resolve, 300));
    }
    
    async function delayedLog(item) {
      // biz Promise üçün await istifadə edə bilərik
      // hansı ki, delay-dan qayıdacaqdır
      await delay();
      console.log(item);
    }
    async function processArray(array) {
      array.forEach(async (item) => {
        await delayedLog(item);
      })
      console.log('Done!');
    }
    
    processArray([1, 2, 3]);
    
        Konsolda gördüyümüz:
    Done!
    1
    2
    3
    
        Bəzi hallarda bu normal bir nəticə hesab oluna bilər. Amma əsasən bu uyğun olmayan bir məntiqdir.

    2. Dövrün növbəli emalı
        Dövrün bədəninin bitdikdən sonra nəticəsini gözləmək üçün biz “for”-dan istifadə etməliyik. Amma bu dəfə biz onun yeni - for..of konstruksiyalı versiyasından yararlanacağıq (Təşəkkürlər Iteration Protocol):
    async function processArray(array) {
      for (const item of array) {
        await delayedLog(item);
      }
      console.log('Done!');
    }
    
        Bu bizə istədiyimiz nəticəni verəcək:
    1
    2
    3
    Done!
    
        Massivin hər bir elementi ardıcıllıq ilə emal olunacaq. Amma biz dövrü paralel də buraxa bilərik!
    3. Dövrün paralel emalı
        Əməliyyatları paralel işlətmək üçün kodu azca dəyişməliyik:
    async function processArray(array) {
      // massivin "map"-ini promislərə göndəririk
      const promises = array.map(delayedLog);
      // bütün promislərin bitməsini gözləyirik
      await Promise.all(promises);
      console.log('Done!');
    }
    
        Bu kod bir neçə delayLog tapşırığı paralel buraxa bilər. Amma böyük massivlərlə ehtiyyatlı olun. Tapşırıq nə qədər çox olsa bu, CPU və yaddaş üçün o qədər də ağır olacaqdır.
         Həmçinin, xahiş edirəm, “paralel tapşırıqları” real paralellik və axınlar ilə çaşdırmayın. Bu kod tam paralel işləməyə zəmanət vermir. Hər şey dövrün bədənindən asılıdır (delayedLog-daki nümunədəki kimi). Şəbəkə sorğuları, webworkers и və bəzi digər tapşırıqlar paralel işlənə bilər.
    Linki kopyala

    Bənzər xəbərlər

    Oxşar xəbərlər