摘要:引擎線程也稱為內核,負責處理腳本程序例如引擎引擎線程負責解析腳本,運行代碼。對象代表一個未完成但預計將來會完成的操作。注意一旦新建就會立即執行它屬于,無法取消。
寫在前面:
第一遍學Promise時, 只是大概過了一遍, 感覺學的不夠深入, 這一篇算是對之前的一個總結吧. Promise在ES6中也屬于一個較難理解的一部分; 所以在學習一個比較難理解的知識點時, 我們可以圍繞這個知識點進行展開,逐個去理解.
理解一個知識點, 不妨先列出下面幾個問題.
Promise是用來干什么的?
Promise是什么?
Promise如何去創建,使用?
Promise的常用形式?
Promise的使用有哪些注意點?
異步相關背景介紹 瀏覽器內核首先聊一下瀏覽器, 一直對瀏覽器的結構比較好奇,查了很多資料總結就有下面一點相關總結; 其中也借鑒其他人的一些東西.
瀏覽器是多進程的,有主進程, GPU加速進程,渲染進程(內核)等, 一般新開一個tab頁面就是新啟動一個進程, CPU就會給他分配資源; 但其中有一個核心進程==>渲染進程(瀏覽器內核), 是我們前端人員需要特別關注的,它包括了多個線程...
GUI渲染線程
負責渲染瀏覽器界面,解析HTML,CSS,構建DOM樹和RenderObject樹,布局和繪制等。 當界面需要重繪(Repaint)或由于某種操作引發回流(reflow)時,該線程就會執行 注意,GUI渲染線程與JS引擎線程是互斥的,當JS引擎執行時GUI線程會被掛起(相當于被凍結了), GUI更新會被保存在一個隊列中等到JS引擎空閑時立即被執行。
JS引擎線程
也稱為JS內核,負責處理Javascript腳本程序.(例如V8引擎)JS引擎線程負責解析Javascript腳本,運行代碼。 JS引擎一直等待著任務隊列中任務的到來,然后加以處理,一個Tab頁(renderer進程)中無論什么時候都只有一個JS線程在運行JS程序 同樣注意,GUI渲染線程與JS引擎線程是互斥的,所以如果JS執行的時間過長,這樣就會造成頁面的渲染不連貫,導致頁面渲染加載阻塞。 不過H5中新增了Web Worker, 實現了多線程: js會新開線程來處理一些其他任務,但不會影響DOM結構... 創建Worker時,JS引擎向瀏覽器申請開一個子線程(子線程是瀏覽器開的,完全受主線程控制,而且不能操作DOM) JS引擎線程與worker線程間通過特定的方式通信 (postMessage API,需要通過序列化對象來與線程交互特定的數據)
事件觸發線程
這個線程是歸屬于瀏覽器而不是JS引擎,用來控制事件循環(可以理解,JS引擎自己都忙不過來,需要瀏覽器另開線程協助) 當JS引擎執行代碼塊如setTimeOut時(也可來自瀏覽器內核的其他線程,如鼠標點擊、AJAX異步請求, 頁面滾動等),會將對應任務添加到事件線程中 當對應的事件符合觸發條件被觸發時,該線程會把事件添加到待處理隊列的隊尾,等待JS引擎的處理 注意, 由于JS的單線程關系,所以這些待處理隊列中的事件都得排隊等待JS引擎處理(當JS引擎空閑時才會去執行)
定時觸發器線程
即setInterval與setTimeout所在線程 瀏覽器定時計數器并不是由JavaScript引擎計數的,(因為JavaScript引擎是單線程的, 如果處于阻塞線程狀態就會影響記計時的準確); 因此通過多帶帶線程來計時并觸發定時(計時完畢后,添加到事件隊列中,等待JS引擎空閑后執行) 當然setTimeout中的延時參數也不一定準確
異步HTTP請求線程
在XMLHttpRequest在連接后是通過瀏覽器新開一個網絡線程去請求 將檢測到狀態變更時,如果設置有回調函數,異步線程就產生狀態變更事件, 將這個回調再放入事件隊列中。再由JavaScript引擎執行。
那么關于瀏覽器方面的背景知識就介紹到這里啦, 想要深入去了解,可以去查相關資料...
事件隊列和循環大家都知道JavaScript引擎是單線程的工作模式, 即同一時間只能跑一段代碼,還要按順序自上而下執行; 但是碰到I/O操作, 定時器, 事件監聽函數等這些耗時操作; JS引擎不會等待它們有結果了才去之下它們后面的代碼, 而是會將它們扔進任務(事件)隊列中, 等待同步代碼執行棧空了之后, 再去任務隊列將任務一個個取出來執行任務所對應的回調函數, 執行完畢后會一直等待新的任務到來; 如此循環...
幾個類型的回調同步回調函數
我們可以利用了函數的執行棧順序,函數作為參數放到另一個函數中調用, 誰在后面調用誰就先被放在函數執行棧棧頂
異步回調函數
事先在外面定義好一個callback; 將回調函數作為某個函數的參數, 利用函數的作用域將函數中異步任務得到的結果存在回調函數的形參中, 然后在函數體末尾調用...
定時器
setTimeout的作用是在間隔一定的時間后,將回調函數插入任務隊列中,等棧中的同步任務都執行完畢后,再執行, 當然這個時間不一定準確...
看阮老師的ES6出門上說Promise是JS異步編程的一種解決方案. 舉個例子, Ajax的回調問題, 如果下一個ajax請求要用到上一個Ajax請求中的結果, 那么往往就會導致多個回調嵌套的問題, 那么Promise就可以解決這種代碼上的嵌套問題, 是我們的代碼變得更優美, 更利于維護; 我暫時先對Promise的理解就是: 處理異步任務, 保存異步結果狀態, 異步代碼同步化...
Promise是什么?Promise 它就是一個對象,相當于一個容器, 里面存的就是一個異步操作的結果; 我們可以是從中獲取異步操作結果的相關信息。
Promise對象代表一個未完成、但預計將來會完成的操作。
它有以下三種狀態:
pending:初始值,不是fulfilled,也不是rejected
fulfilled:代表操作成功
rejected:代表操作失敗
Promise有兩種狀態改變的方式,既可以從pending轉變為fulfilled,也可以從pending轉變為rejected。一旦狀態改變,就「凝固」了,會一直保持這個狀態,不會再發生變化。當狀態發生變化,promise.then綁定的函數就會被調用。
注意:Promise一旦新建就會「立即執行」(它屬于microtask),無法取消。這也是它的缺點之一。
1.創建promise對象
//1.使用new Promise(func)的形式 //2.快捷語法: Promise.resolve(func) || Promise.reject(func) // 參數1: 一般是一個處理異步任務的函數 // 返回值: 一個promise實例對象 Promise.resolve("foo") // 等價于, 不過參數類型不一樣執行的操作也會有所不同 new Promise(resolve => resolve("foo"))
2.在函數func中 放異步處理代碼
// 傳入兩個參數: 回調函數resolve, reject分別去保存異步處理的結果 // 成功: 使用resolve(結果) // 失敗: 使用reject(原因)
3.調用實例的then(func1) 或者 catch(err)
首先then方法是異步執行, 對上面的異步結果進行處理的函數 參數: 傳回調函數, 一個兩個都行, 前者是成功狀態的回調,后者是失敗的回調Promise常用的場景?
promise一般的使用套路就是:
1.先定義一個函數, 函數內部使用new Promise()的方式來返回一個promise對象, resolve用來保存 異步處理成功的結果 reject用來保存 異常處理的結果 2.然后函數調用,傳參 3.鏈式語法點出then方法, then中的回調用來處理異步結果 4.有錯誤就點出catch方法, 也可以用then(null, function() {})代替catch 5.then的回調中也可return一個值, 會被包裝成一個新的promise, 因此可以繼續調用then方法
應用場景: 在ajax中使用, 解決異步嵌套問題
function ajax(url) { return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest(); // 請求類型, 地址, 異步 xhr.open("get", url, true); xhr.send(); xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { try { // 處理響應內容, 將內容丟到成功狀態的回調 resolve(JSON.parse(xhr.responseText)) } catch (e) { // 捕獲錯誤, 丟到失敗狀態的回調 reject(e) } } } }); } // 調用 封裝的ajax函數 let url = "http://127.0.0.1:3000/xxoo"; // 自己本地開的一個服務 ajax(url) .then(res => console.log(res)) // 輸出 {code: 0, msg: "hello cors"} .catch(err => console.log(err)) ```
其他場景
// 實現串行任務管道; 即當前任務的輸出可以作為下一個任務的輸入,形成一條數據管道; // 比如: 比如從url1獲取參數userId,拿到后再從url2獲取第三方openId,最后再從url3貨取orderList, 然后把結果展示給用戶,類似的邏輯都是任務管道: new Promise(function(resolve, reject) { resolve(1); }) .then(function(res) { return new Promise(function(resolve, reject) { resolve(res + 1); }); }) .then(function(res) { return new Promise(function(resolve, reject) { resolve(res + 1); }); }) .then(function(res) { console.log(res); // 3 });promise的好處
在異步執行的流程中,使用Promise可以把 執行代碼 和 處理結果 的代碼清晰地分離
這樣我們便可以 把執行代碼 和 結果處理 分成不同的模塊來寫,易于維護
減少異步回調的嵌套, 比如ajax回調, 我們可以依次調用then方法即可, 還可以控制回調的順序
多個異步任務是為了容錯去訪問用同一資源時, 可以使用Promise.race([promise實例...])
多個異步任務并行執行時,比如ajax訪問兩個接口, 可以用Promise.all([promise實例...])
Promise使用的注意事項Promise構造函數內的同步代碼立即執行
回調函數參數resolve異步執行, 將結果作為參數傳給then方法中的回調函數
resolve只有第一次執行有效,狀態不能二次改變
then和catch如果有return, 返回的是一個全新的promise對象, 可以鏈式調用
Promise構造函數只會執行一次, promise實例會保存resolve的狀態,
以后這個實例每次調用then都是返回一個這個狀態, 若鏈式調用then,下一個則會打印undefined, res沒有值...
then中返回任意一個非 promise 的值都會被包裹成 promise 對象
.then 或 .catch 返回的值不能是 promise 本身,否則會造成死循環
.then 或者 .catch 的參數期望是函數,傳入非函數則會發生值穿透。
.then 可以接收兩個參數,第一個是處理成功的函數,第二個是處理錯誤的函數。.catch 是 .then 第二個參數的簡便寫法,但是它們用法上有一點需要注意:.then 的第二個處理錯誤的函數捕獲不了第一個處理成功的函數拋出的錯誤,而后續的 .catch 可以捕獲之前的錯誤。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102596.html
Promise/async、await幫我們解決了什么 它給我們提供了一種新的異步編程解決方案,同時避免了困擾已久的回調地獄 // 異步的處理可能會產生這樣的回調地獄(第二個異步操作和第一個異步的結果有關系) let Ajax = function(data, success, error){ $.ajax({ data: data, success: function...
Promise/async、await幫我們解決了什么 它給我們提供了一種新的異步編程解決方案,同時避免了困擾已久的回調地獄 // 異步的處理可能會產生這樣的回調地獄(第二個異步操作和第一個異步的結果有關系) let Ajax = function(data, success, error){ $.ajax({ data: data, success: function...
Promise/async、await幫我們解決了什么 它給我們提供了一種新的異步編程解決方案,同時避免了困擾已久的回調地獄 // 異步的處理可能會產生這樣的回調地獄(第二個異步操作和第一個異步的結果有關系) let Ajax = function(data, success, error){ $.ajax({ data: data, success: function...
摘要:的翻譯文檔由的維護很多人說,阮老師已經有一本關于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。 JavaScript Promise 迷你書(中文版) 超詳細介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...
摘要:學習地址詳見正文調用或并不會終結的參數函數的執行調用以后,后面的還是會執行,并且會首先打印出來。這是因為立即的是在本輪事件循環的末尾執行,總是晚于本輪循環的同步任務。另外,方法指定的回調函數,如果運行中拋出錯誤,也會被方法捕獲。 學習地址詳見:http://es6.ruanyifeng.com/#do... 正文 1.調用resolve或reject并不會終結 Promise 的參數函...
閱讀 4149·2021-09-22 15:34
閱讀 2765·2021-09-22 15:29
閱讀 490·2019-08-29 13:52
閱讀 3351·2019-08-29 11:30
閱讀 2259·2019-08-26 10:40
閱讀 832·2019-08-26 10:19
閱讀 2256·2019-08-23 18:16
閱讀 2311·2019-08-23 17:50