前言
“JS 是基于單線程事件循環”的概念構建的,回調函數不會立即執行,由事件輪詢去檢測事件是否執行完畢,當執行完有結果后,將結果放入回調函數的參數中,然后將回調函數添加到事件隊列中等待被執行。
同時也講了回調函數的問題:
一是“回調地獄”,因為異步回調函數的特點:回調函數是作為異步函數的參數,一層一層嵌套,當嵌套過多,將使代碼邏輯變得混亂,也無法做好錯誤捕捉和處理(只能在回調函數內部 try catch)。
二是回調的執行方式不符合自然語言的線性思維方式,不容易被理解。
三是控制反轉(控制權在其他人的代碼上),假如異步函數是別人提供的庫,我們把回調函數傳進去,我們并不能知道異步函數在調用回調函數之外做了什么事情。
func1(() => {func2(() => {func3(() => {func4(() => {try {...} catch (err){...}})});});});
一、Promise 原理
首先,Promise 中文翻譯為“承諾”, 是 JavaScript 的一種對象,表示承諾終將返回一個結果,無論成功還是失敗。
Promise 有三個狀態:等待中(pending),完成(fullfilled),失?。╮ejected), 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 somethingconsole.log(result);return 1// return Promise.resolve(1); // 返回一個決議為成功的 promise 實例// return Promise.reject("error"); // 返回一個決議為拒絕的 Promise 實例}).then((result) => {// .then() 方法會返回一個 promise, 完成調用的參數為前一個 promise 的返回值或者決議值。// do other thingsconsole.log(result);throw new Error("錯誤") // 拋出錯誤是隱式拒絕}).catch((error) => {// 捕捉錯誤console.log(error)}).then(() => {// 還能繼續執行!}).finally(() => {// always do somethingsconsole.log("finally!")})
二、Promise 的優勢
1.鏈式調用
Promise 使用 then 方法后還會返回一個新的 Promise 對象,便于我們傳遞狀態數據,同時鏈式寫法接近于同步寫法,更符合線性思維。
2.錯誤捕捉
相比回調函數的錯誤無法在外部捕捉的問題,Promise 能夠為一連串的異步調用提供錯誤處理。
3.控制反轉再反轉
由于第三方提供的異步函數,無法保證回調函數如何被執行,但是 Promise 的特點,能夠保證異步函數只能被 resolve 一次,以及始終以異步的形式執行代碼。
4.可以利用 Promise.all 和 Promise.race 來解決 Promise 始終未決議和并行 Promise 嵌套的問題
三、Promise 的不足
1.每個 .then() 都是一個獨立的作用域
加入有很多個 .then() 方法,就會創建很多個獨立的作用域,那么將只能通過外面包裹一層函數作用域的閉包來共享狀態數據
2.無法取消單個 .then()
當 Promise 鏈中任意一個 .then() 方法中有語句執行錯誤后,盡管經過 catch 方法的錯誤處理,還是并不會中斷整個 Promise 鏈的執行。
3.無法得知進度
由于 Promise 只能從 pending 到 fullfilled 或 rejected 狀態,無法得知 pending 階段的進度。
四、Promise 應用
// Promise 封裝 ajaxfunction 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 在事件輪詢中屬于異步事件隊列中的微任務,而微任務總是一次性全部執行,而宏任務是每輪輪詢執行一個。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。
新聞熱點
疑難解答