摘要:三是控制反轉控制權在其他人的代碼上,假如異步函數是別人提供的庫,我們把回調函數傳進去,我們并不能知道異步函數在調用回調函數之外做了什么事情。錯誤捕捉相比回調函數的錯誤無法在外部捕捉的問題,能夠為一連串的異步調用提供錯誤處理。
前言
《JS異步編程之 callback》一文我們了解了“JS 是基于單線程事件循環”的概念構建的,回調函數不會立即執行,由事件輪詢去檢測事件是否執行完畢,當執行完有結果后,將結果放入回調函數的參數中,然后將回調函數添加到事件隊列中等待被執行。
同時也講了回調函數的問題:
一是“回調地獄”,因為異步回調函數的特點:回調函數是作為異步函數的參數,一層一層嵌套,當嵌套過多,將使代碼邏輯變得混亂,也無法做好錯誤捕捉和處理(只能在回調函數內部 try catch)。
二是回調的執行方式不符合自然語言的線性思維方式,不容易被理解。
三是控制反轉(控制權在其他人的代碼上),假如異步函數是別人提供的庫,我們把回調函數傳進去,我們并不能知道異步函數在調用回調函數之外做了什么事情。
func1(() => { func2(() => { func3(() => { func4(() => { try { ... } catch (err){ ... } }) }); }); });一、Promise 原理
首先,Promise 中文翻譯為“承諾”, 是 JavaScript 的一種對象,表示承諾終將返回一個結果,無論成功還是失敗。
Promise 有三個狀態:等待中(pending),完成(fullfilled),失敗(rejected), Promise 的設計具有原子性,狀態一旦從 pending 狀態轉換為 fullfilled 狀態或者 rejected 狀態后,將不能被改變。
var promise1 = new Promise((resolve, reject) => { console.log("Promise 構造器會立即執行"); setTimeout(function (){ if(true) { resolve("完成"); } else { reject("失敗"); } }, 1000); }) promise1 .then((result) => { // do something console.log(result); return 1 // return Promise.resolve(1); // 返回一個決議為成功的 promise 實例 // return Promise.reject("error"); // 返回一個決議為拒絕的 Promise 實例 }) .then((result) => { // .then() 方法會返回一個 promise, 完成調用的參數為前一個 promise 的返回值或者決議值。 // do other things console.log(result); throw new Error("錯誤") // 拋出錯誤是隱式拒絕 }) .catch((error) => { // 捕捉錯誤 console.log(error) }) .then(() => { // 還能繼續執行! }) .finally(() => { // always do somethings console.log("finally!") })二、Promise 的優勢
鏈式調用
Promise 使用 then 方法后還會返回一個新的 Promise 對象,便于我們傳遞狀態數據,同時鏈式寫法接近于同步寫法,更符合線性思維。
錯誤捕捉
相比回調函數的錯誤無法在外部捕捉的問題,Promise 能夠為一連串的異步調用提供錯誤處理。
控制反轉再反轉
由于第三方提供的異步函數,無法保證回調函數如何被執行,但是 Promise 的特點,能夠保證異步函數只能被 resolve 一次,以及始終以異步的形式執行代碼。
可以利用 Promise.all 和 Promise.race 來解決 Promise 始終未決議和并行 Promise 嵌套的問題
三、Promise 的不足每個 .then() 都是一個獨立的作用域
加入有很多個 .then() 方法,就會創建很多個獨立的作用域,那么將只能通過外面包裹一層函數作用域的閉包來共享狀態數據
無法取消單個 .then()
當 Promise 鏈中任意一個 .then() 方法中有語句執行錯誤后,盡管經過 catch 方法的錯誤處理,還是并不會中斷整個 Promise 鏈的執行。
無法得知進度
由于 Promise 只能從 pending 到 fullfilled 或 rejected 狀態,無法得知 pending 階段的進度。
四、Promise 應用// Promise 封裝 ajax function fetch(method, url, data){ return new Promise((resolve, reject) => { var xhr = new XMLHttpRequest(); var method = method || "GET"; var data = data || null; xhr.open(method, url, true); xhr.onreadystatechange = function() { if(xhr.status === 200 && xhr.readyState === 4){ resolve(xhr.responseText); } else { reject(xhr.responseText); } } xhr.send(data); }) } // 使用 fetch("GET", "/some/url.json", null) .then(result => { console.log(result); }) // 封裝 nodejs error first 風格回調 function readFile(url) { return new Promise((resolve, reject) => { fs.readFile(url,"utf8", (err, data) => { if(err) { reject(err); return; } resolve(data) }) }) }五、總結
Promise 是 ES6 提出的簡化異步流程控制的新規范,強調異步任務的完成狀態且具有原子性,這使得我們的代碼更容易追蹤和維護。Promise 在事件輪詢中屬于異步事件隊列中的微任務,而微任務總是一次性全部執行,而宏任務是每輪輪詢執行一個,此節內容參考我之前的文章《JS專題之事件循環》。
2019/02/24 @Manncoffee
歡迎關注我的個人公眾號“謝南波”,專注分享原創文章。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102060.html
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。異步編程入門的全稱是前端經典面試題從輸入到頁面加載發生了什么這是一篇開發的科普類文章,涉及到優化等多個方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結思考,循序漸進的理解 TypeScript。 網絡基礎知識之 HTTP 協議 詳細介紹 HTT...
摘要:因為瀏覽器環境里是單線程的,所以異步編程在前端領域尤為重要。除此之外,它還有兩個特性,使它可以作為異步編程的完整解決方案函數體內外的數據交換和錯誤處理機制。 showImg(https://segmentfault.com/img/bVz9Cy); 在我們日常編碼中,需要異步的場景很多,比如讀取文件內容、獲取遠程數據、發送數據到服務端等。因為瀏覽器環境里Javascript是單線程的,...
摘要:異步編程解決方案筆記最近讀了樸靈老師的深入淺出中異步編程一章,并參考了一些有趣的文章。另外回調函數中的也失去了意義,這會使我們的程序必須依賴于副作用。 JavaScript 異步編程解決方案筆記 最近讀了樸靈老師的《深入淺出NodeJS》中《異步編程》一章,并參考了一些有趣的文章。在此做個筆記,記錄并鞏固學到的知識。 JavaScript異步編程的兩個核心難點 異步I/O、事件驅動使得...
摘要:的翻譯文檔由的維護很多人說,阮老師已經有一本關于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。 JavaScript Promise 迷你書(中文版) 超詳細介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...
摘要:函數會在之后的某個時刻觸發事件定時器。事件循環中的這樣一次遍歷被稱為一個。執行完畢并出棧。當定時器過期,宿主環境會把回調函數添加至事件循環隊列中,然后,在未來的某個取出并執行該事件。 原文請查閱這里,略有改動。 本系列持續更新中,Github 地址請查閱這里。 這是 JavaScript 工作原理的第四章。 現在,我們將會通過回顧單線程環境下編程的弊端及如何克服這些困難以創建令人驚嘆...
閱讀 2654·2023-04-25 15:22
閱讀 2824·2021-10-11 10:58
閱讀 1045·2021-08-30 09:48
閱讀 1851·2019-08-30 15:56
閱讀 1730·2019-08-30 15:53
閱讀 1089·2019-08-29 11:16
閱讀 1048·2019-08-23 18:34
閱讀 1638·2019-08-23 18:12