Синхронное и асинхронное программирование в Javascript.

Javascript — это однопоточный язык программирования, который также может быть неблокирующим. Это просто означает, что javascript — это язык программирования, который можно использовать для выполнения синхронных и асинхронных задач.

Эти два стиля программирования дают javascript много возможностей, когда дело доходит до выполнения задач программирования, особенно тех, которые требуют длительного времени для завершения.

В этой статье я расскажу о различиях между синхронным и асинхронным программированием, о плюсах и минусах каждого из них, а также об их наилучших вариантах использования.

Различия.

  • Обычные функции возвращают результат с помощью ключевого слова return, в то время как асинхронные функции возвращают объект Promise (это объект, который содержит состояние обещания и значение обещания).

     function sum(a,b) {
          return a+b;
     }
    
     async function add(a,b) {
          return a + b;
     }
    
     sum(3,9)
     add(3,9)
    

  • Значения обычной функции получаются при вызове функции, а значения Async-функции — при использовании await или .then().

     function sum(a,b) {
          return `Normal function : ${3 + 9}`;
     }
    
     async function add(a,b) {
          return  a + b;
     }
    
     sum(3,9)
     await add(3,9)
    

    Использование .then()

     add(3,9).then((value)=> console.log(value))
    

  • Большинство функций/методов, которые естественным образом работают асинхронно, требуют в качестве параметра функцию обратного вызова.

     new Promise((resolve)=>resolve);
     setTimeout(()=>,1000);
     element.addEventListener("click", ()=>)
    

    В синхронном программировании функции, которые требуют другие функции в качестве параметров, называются функциями высшего порядка.

     function multiplyBy(num) {
          return function(arg) {
              return  num * arg;
          }
     }
     const multiplyByTwo = mutltiplyBy(2);
     const multiplyByFour = multiplyBy(4);
     multiplyByTwo(4)
     multiplyByFour(4)
    
  • Движок javascript сначала выполняет весь синхронный код, прежде чем запускать асинхронный код.

     console.log("I am the first") //synchronous
     new Promise((resolve)=>resolve("I am second")).then(console.log); //asynchronous
     setTimeout(console.log("I am the third"), 2) // asynchronous
     console.log("Should I be the last")  //synchronous
     setTimeout(console.log("Can I come ?"), 0) // asynchronous
    
    

  • В Javascript все асинхронные коды сначала отправляются в веб-интерфейс API, а затем добавляются в стек вызовов. Асинхронные коды добавляются в стек вызовов, когда все синхронные коды выполнены движком javascript и удалены из стека вызовов.

     function printHello() {
     console.log('Hello from baz');
     }

     function baz() {
     setTimeout(printHello, 3000);
     }

     function bar() {
     baz();
     }

     function foo() {
     bar();
     }

     foo();
Вход в полноэкранный режим Выход из полноэкранного режима

  • Синхронное программирование следует строгой последовательности, что означает, что операции выполняются в идеальном порядке. Пока выполняется одна операция, инструкции других операций блокируются.

        console.log("Loading file-1 ...")
        console.log("Loading file-2 ...")
        console.log("Loading file-3 ...")
    

    При синхронном программировании было бы невозможно загрузить файл-2 без загрузки файла-1.

    Асинхронное программирование является неблокирующим, что означает, что оно не блокирует дальнейшее выполнение, пока одна или несколько операций находятся в процессе выполнения. Это также означает, что несколько операций могут выполняться одновременно, не дожидаясь завершения других задач.

        new Promise((resolve)=>setTimeout(resolve("Loading file-1"),2000)).then(console.log);
    
        setTimeout(console.log("Loadinf file-2"),0);
    
        btn.addEventListener("click", ()=>console.log("Loading file-3"));
    
  • Функции Javascript, которые занимают очень много времени, прежде чем вернуться, могут сделать пользовательский интерфейс (UI) или сервер невосприимчивым, пока функция не вернется, что приведет к плохому пользовательскому опыту. Примером может быть использование функции alert для отображения сообщения.
    Пользователь не сможет ничего сделать на веб-странице, пока не будет получен ответ от окна оповещения.

          console.log("Loading file-1 ...")
          alert("Loading file-2 ...")
          console.log("Loading file-3 ...")
    

    Асинхронное программирование повышает удобство работы пользователя, сокращая время, необходимое для возврата функции после ее вызова. Для этого сложные функции выполняются в фоновом режиме, чтобы не прерывать работу пользователя с приложением.

    Например, для получения данных из интерфейса прикладного программирования (API) или чтения файла требуется время, поэтому вместо остановки всех остальных операций мы можем использовать асинхронное программирование для выполнения этих действий. Бонусом здесь является то, что пользователю может показаться, что приложение работает очень быстро.

         function load(file) {
              return new Promise((resolve)=>{
                   resolve(file)
              });
         };
    
         async function getBigData(bigFile) {
              const respone = await load(bigFile);
              console.log(`${bigFile} is ready`);
         };
    
         function getsmallData(smallFile) {
              console.log(`${smallFile} is ready`);
         };
    
         getBigData("File-1");
         loadsmallData("File-2");
         loadsmallData("File-3");
         loadsmallData("File-4");
    

    «Файл-1» очень большой, и его синхронная загрузка может замедлить работу нашего приложения. Поэтому мы загружаем его асинхронно, используя Promise.

    Как только движок javascript замечает, что getBigData() является асинхронной функцией, он отправляет ее в web API и продолжает выполнять другие синхронные задачи.

    После завершения всех синхронных задач цикл событий проверяет очередь микрозадач/очередь заданий и запускает getBigData() на стеке вызовов.

  • Асинхронный код является неблокирующим, что означает, что мы можем отправлять несколько запросов на сервер одновременно.

         const urls = [
             'https://jsonplaceholder.typicode.com/users',
             'https://jsonplaceholder.typicode.com/posts',
             'https://jsonplaceholder.typicode.com/albums'
         ];
    
         Promise.all(urls.map((url) => {
              return fetch(url).then((value) => value.json());
              })).then((values) => {
                  console.log(values[0]);
                  console.log(values[1]);
                  console.log(values[2]);
         }).catch((error) => console.log("Opps there was an error", error));
    

    Синхронный код является блокирующим, что означает, что он может отправить только один запрос и ждать ответа от сервера.

С помощью Promise.all() мы можем работать над массивом асинхронных операций одновременно, то есть использовать fetch() для получения данных из базы данных.

  • Синхронное программирование выгодно разработчикам, потому что его гораздо проще кодировать. Это экономит время, необходимое разработчикам для изучения того, что может открыть дверь для ошибок (асинхронное программирование).

  • Асинхронное программирование следует использовать при выполнении задач, выполнение которых не зависит от других задач.

         <!DOCTYPE html>
         <html>
              <p>Hello</p>
              <p>Hello</p>
              <p>Hello</p>
              <p>Hello</p>
              <p>Hello</p>
              <p>Hello</p>
              <p>Hello</p>
              <script src="animate.js"></script>
              <script src="index.js"></script>
         </html>
    

    Предположим, мы хотим анимировать теги p после загрузки страницы с помощью библиотеки анимации javascript (animate.js). Поскольку наш код, написанный в index.js, зависит от кода, написанного в animate.js, он размещается после него.

    Код в index.js является зависимой задачей, потому что он зависит от animate.js для успешного выполнения своей работы, в то время как библиотека animate.js является независимой задачей, потому что она не зависит от какого-либо другого кода для своего выполнения.

    Код считывается синхронно от тегов p до последнего файла сценария, index.js, и все работает, как и ожидалось. Но мы могли бы сделать кое-что интересное, загрузив animate.js асинхронно. Это означает, что файл сценария animate.js разбирается одновременно с тегами p, чтобы увеличить время загрузки.

          <script async src="animate.js"></script>
    

    При добавлении ключевого слова async файл animate.js загружается одновременно со всеми тегами p. Круто, правда?

    Благодаря этому мы получаем прирост времени загрузки, а наши пользователи остаются довольны ☺.

  • Поисковым системам легче находить веб-страницы, использующие синхронное программирование. Поэтому для бизнеса, который зависит от поисковой оптимизации (SEO) для продвижения своей репутации и продукта, синхронное программирование будет ощутимым преимуществом.

Заключение

Я надеюсь, что вы почерпнули что-то новое из этой статьи и сможете принимать мудрые решения по программированию в соответствии с тем, что требуется вашему приложению.

Ссылки

  • Асинхронники против синхронников

  • Блог Trio

  • Loupe

Оцените статью
devanswers.ru
Добавить комментарий