搜尋
首頁web前端js教程手把手帶你去理解JavaScript中的非同步編程
手把手帶你去理解JavaScript中的非同步編程Jun 03, 2021 am 11:02 AM
javascript非同步程式設計

本篇文章帶大家了解JavaScript中的非同步程式設計。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。

手把手帶你去理解JavaScript中的非同步編程

異步,就是非同步....

這節內容可能會有點枯燥,但是卻是JavaScript 中非常重要的概念,非常有必要去學習。

目的

  • 提升開發效率,寫出易維護的程式碼

引子問題

  • 請求時候為什麼頁面卡死? ?
$.ajax({
  url: "www.xx.com/api",
  async: false, // true
  success: function(result) {
    console.log(result);
  },
});
  • 為什麼資料更新了,DOM 沒有更新? ?
// 异步批量更新DOM(vue-nextTick)
// <p id="app">{{num}}</p>
new Vue({
  el: "#app",
  data: {
    num: 0,
  },
  mounted() {
    let dom = document.getElementById("app");
    while (this.num !== 100) {
      this.num++;
    }
    console.log("Vue num=" + this.num, "DOM num=" + dom.innerHTML);
    // Vue num=100,DOM num=0
    // nextTick or setTimeout
  },
});

產生非同步的原因

原因:單一線程(一個時間點,只做一件事),瀏覽器的JS 引擎是單線程導致的。

單執行緒是指在 JS 引擎中負責解釋和執行 IavaScript 程式碼的執行緒只有一個,不妨叫它主執行緒。

所謂單線程,就是指一次只能完成一件任務。如果有多個任務,就必須排隊,前面一個任務完成再執行後面一個任務。

先來看看瀏覽器核心的執行緒圖:

手把手帶你去理解JavaScript中的非同步編程

#其中,渲染執行緒與JS 執行緒互斥

假設有兩個函數,一個修改一個刪除,同時操作一個 DOM 節點,假如有多個執行緒的話,兩個執行緒一起執行,肯定就死鎖了,就會有問題。

為什麼 JS 要設計為單線程,因為瀏覽器的特殊環境。

單一執行緒的優缺點:

這種模式的好處是實現起來比較簡單,執行環境相對單純;壞處是只要有一個任務耗時很長,後面的任務都必須排隊等著,會拖延整個程式的執行。常見的瀏覽器無回應(假死),往往是因為某一段 Javascript 程式碼長時間運行(例如死循環),導致整個頁面卡在這個地方,其他任務無法執行。

常見的堵塞(死循環):

while (true) {}

JS 在設計之初就以運行在瀏覽器中的腳本語言,所以也不想搞得這麼複雜,就設計成了單線程,也就是,一個時間點,只能做一件事。

為了解決單執行緒阻塞這個缺點:產生了非同步。

拿吃泡麵舉例:

  • 同步:買泡麵=》燒水(盯著)=》煮麵=》吃泡麵
  • 異步:買泡麵=》燒水(水開了熱水壺響-回調)=》看電視=》煮麵(面好了熱水壺響-回調)=》看電視=》熟了叫我=》吃泡面

看電視就是非同步操作,熱水壺響,就是回呼函數。

非同步程式設計

JS 中大多的程式碼都是同步執行的,只有極個別的函數是非同步執行的,非同步執行的程式碼,則需要非同步程式設計。

非同步程式碼

setTimeout(() => {
  console.log("log2");
}, 0);
console.log("log1");
// ?? log1 log2

非同步程式碼的特點:不是立即執行,而是需要等待,在未來的某一個時間點執行。

同步程式碼 #非同步程式碼
<script></script>程式碼 網路請求(Ajax)
I/O 操作 計時器(setTimeout、setInterval)
渲染操作 Promise(then)

  • #async/await


手把手帶你去理解JavaScript中的非同步編程回呼函數

非同步程式碼最常見的寫法就是使用回呼函數。

    HTTP 網路請求(請求成功、識別後執行xx 操作)
  • DOM 事件綁定機制(使用者觸發事件後執行xx 操作)
    計時器(setTimeout、setInterval)(在達到設定時間後執行xx 操作)
  • // 注意到click方法中是一个函数而不是一个变量
    // 它就是回调函数
    $("#btn_1").click(function() {
      alert("Btn 1 Clicked");
    });
    // 或者
    function click() {
      // 它就是回调函数
      alert("Btn 1 Clicked");
    }
    $("#btn_1").click(click);
回呼函數的缺點也很明顯,容易產生回呼地獄:

非同步程式設計的三種方式

callback
function getOneNews() {
  $.ajax({
    url: topicsUrl,
    success: function(res) {
      let id = res.data[0].id;
      $.ajax({
        url: topicOneUrl + id,
        success: function(ress) {
          console.log(ress);
          render(ress.data);
        },
      });
    },
  });
}

promise

function getOneNews() {
  axios
    .get(topicsUrl)
    .then(function(response) {
      let id = response.data.data[0].id;
      return axios.get(topicOneUrl + id);
    })
    .then((res) => {
      render(res.data.data);
    })
    .catch(function(error) {
      console.log(error);
    });
}
async/await

async function getOneNews() {
  let listData = await axios.get(topicsUrl);
  let id = listData.data.data[0].id;
  let data = await axios.get(topicOneUrl + id);
  render(data.data.data);
}

線上預覽問題? ? 巨集任務和微任務巨集任務(不急)
預覽網址:http://jsrun.net/s43Kp/embedded/all/ light 如果多個非同步程式碼同時存在,那麼執行順序應該是怎麼樣的?那個先執行、那個後執行了?
非同步程式碼的劃分,非同步程式碼分宏任務和微任務。
#微任務(急)
#########<script>###整體程式碼#######Promise############setTimeout/setInterval##### ##################<h2><strong>事件循环(Event loop)<p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/image/559/429/380/1622689034979881.png?x-oss-process=image/resize,p_40" class="lazy" title="1622689034979881.png" alt="手把手帶你去理解JavaScript中的非同步編程"/><p>执行顺序:<ul style="max-width:90%"><li><p>执行整体代码<code><script>(宏任务)<li><p>执行所有微任务<li><p>执行一个宏任务<li><p>执行渲染线程<li><p>2->3->2->3...依次循环(在 2、3 步中又创建了新的宏、微任务)<p>重复从宏任务和微任务队列里拿出任务去执行。<h2><strong>总结<p>因为浏览器设计的原因,JS 线程和渲染线程互斥,所以 JS 线程被设计成了单线程。<p>因为单线程执行一些操作(如网络请求)时有堵塞的问题,所有产生了异步。<p>因为有了异步,所以产生了异步编程,从而有了回调函数。<p>因为回调函数写多了会产生回调地狱,所有又有了解决回调地狱的 Promise 写法<p>自 ES7 标准后有了比 Promise 更加优雅的写法 ———— async/await 写法,也是异步编程的最终解决方法。<p>因为 JS 的代码分为同步和异步代码,同步代码的执行顺序不必多说,自上而下的执行。<p>但是如果有多个异步的代码,他的执行顺序又是怎么的呢??<p>为了解决多个异步代码的执行顺序问了,有了事件循环(EventLoop),将异步任务区分为宏任务、微任务,依据规则依次执行。<p>至此 完!<h2><strong>练习<pre class='brush:php;toolbar:false;'>console.log(&quot;script start&quot;); setTimeout(function() { console.log(&quot;timeout1&quot;); }, 10); new Promise((resolve) =&gt; { console.log(&quot;promise1&quot;); resolve(); setTimeout(() =&gt; console.log(&quot;timeout2&quot;), 10); }).then(function() { console.log(&quot;then1&quot;); }); console.log(&quot;script end&quot;);</pre><p>写出 log 的输出结果,并说出理由。<p>更多编程相关知识,请访问:<a href="https://www.php.cn/course.html" target="_blank" textvalue="编程视频">编程视频!!</script>

以上是手把手帶你去理解JavaScript中的非同步編程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:segmentfault。如有侵權,請聯絡admin@php.cn刪除
es6数组怎么去掉重复并且重新排序es6数组怎么去掉重复并且重新排序May 05, 2022 pm 07:08 PM

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

JavaScript的Symbol类型、隐藏属性及全局注册表详解JavaScript的Symbol类型、隐藏属性及全局注册表详解Jun 02, 2022 am 11:50 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

原来利用纯CSS也能实现文字轮播与图片轮播!原来利用纯CSS也能实现文字轮播与图片轮播!Jun 10, 2022 pm 01:00 PM

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

JavaScript对象的构造函数和new操作符(实例详解)JavaScript对象的构造函数和new操作符(实例详解)May 10, 2022 pm 06:16 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

javascript怎么移除元素点击事件javascript怎么移除元素点击事件Apr 11, 2022 pm 04:51 PM

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

JavaScript面向对象详细解析之属性描述符JavaScript面向对象详细解析之属性描述符May 27, 2022 pm 05:29 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

foreach是es6里的吗foreach是es6里的吗May 05, 2022 pm 05:59 PM

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。

整理总结JavaScript常见的BOM操作整理总结JavaScript常见的BOM操作Jun 01, 2022 am 11:43 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器