您好,登錄后才能下訂單哦!
這篇文章主要介紹“Promise的原理和基礎用法介紹”,在日常操作中,相信很多人在Promise的原理和基礎用法介紹問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Promise的原理和基礎用法介紹”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
new Promise(function(resolve, reject) { //待處理的異步邏輯 //處理結束后,調用resolve或reject方法 }) |
新建一個
promise
很簡單,只需要new
一個promise
對象即可。所以promise
本質上就是一個函數,它接受一個函數作為參數,并且會返回promise
對象,這就給鏈式調用提供了基礎其實
Promise
函數的使命,就是構建出它的實例,并且負責幫我們管理這些實例。而這些實例有以下三種狀態:
pending
: 初始狀態,位履行或拒絕
fulfilled
: 意味著操作成功完成
rejected
: 意味著操作失敗
pending
狀態的Promise
對象可能以fulfilled
狀態返回了一個值,也可能被某種理由(異常信息)拒絕(reject
)了。當其中任一種情況出現時,Promise
對象的then
方法綁定的處理方法(handlers)就會被調用,then方法分別指定了resolve
方法和reject
方法的回調函數
var promise = new Promise(function(resolve, reject) { if (/* 異步操作成功 */){ resolve(value); } else { reject(error); } }); promise.then(function(value) { // 如果調用了resolve方法,執行此函數 }, function(value) { // 如果調用了reject方法,執行此函數 }); |
上述代碼很清晰的展示了
promise
對象運行的機制。下面再看一個示例:
var getJSON = function(url) { var promise = new Promise(function(resolve, reject){ var client = new XMLHttpRequest(); client.open("GET", url); client.> client.responseType = "json"; client.setRequestHeader("Accept", "application/json"); client.send(); function handler( ) { if (this.status === 200) { resolve(this.response); } else { reject(new Error(this.statusText)); } }; }); return promise; }; getJSON("/posts.json").then(function(json) { console.log('Contents: ' + json); }, function(error) { console.error('出錯了', error); }); |
上面代碼中,
resolve
方法和reject
方法調用時,都帶有參數。它們的參數會被傳遞給回調函數。reject
方法的參數通常是Error
對象的實例,而resolve
方法的參數除了正常的值以外,還可能是另一個Promise
實例,比如像下面這樣。
var p1 = new Promise(function(resolve, reject){ // ... some code }); var p2 = new Promise(function(resolve, reject){ // ... some code resolve(p1); }) |
上面代碼中,
p1
和p2
都是Promise
的實例,但是p2
的resolve
方法將p1
作為參數,這時p1
的狀態就會傳遞給p2
。如果調用的時候,p1
的狀態是pending
,那么p2
的回調函數就會等待p1
的狀態改變;如果p1
的狀態已經是fulfilled
或者rejected
,那么p2
的回調函數將會立刻執行
Promise.prototype.catch
方法是Promise.prototype.then(null, rejection)
的別名,用于指定發生錯誤時的回調函數
getJSON("/visa.json").then(function(result) { // some code }).catch(function(error) { // 處理前一個回調函數運行時發生的錯誤 console.log('出錯啦!', error); }); |
Promise
對象的錯誤具有“冒泡”性質,會一直向后傳遞,直到被捕獲為止。也就是說,錯誤總是會被下一個catch
語句捕獲
getJSON("/visa.json").then(function(json) { return json.name; }).then(function(name) { // proceed }).catch(function(error) { //處理前面任一個then函數拋出的錯誤 }); |
Promise.all方法
Promise.all
方法用于將多個Promise
實例,包裝成一個新的Promise
實例
var p = Promise.all([p1,p2,p3]); |
上面代碼中,Promise.all
方法接受一個數組作為參數,p1
、p2
、p3
都是Promise
對象的實例。(Promise.all
方法的參數不一定是數組,但是必須具有iterator
接口,且返回的每個成員都是Promise
實例。)
p
的狀態由p1
、p2
、p3
決定,分成兩種情況
只有p1
、p2
、p3
的狀態都變成fulfilled
,p
的狀態才會變成fulfilled
,此時p1
、p2
、p3
的返回值組成一個數組,傳遞給p
的回調函數
只要p1
、p2
、p3
之中有一個被rejected
,p
的狀態就變成rejected
,此時第一個被reject
的實例的返回值,會傳遞給p的回調函數
// 生成一個Promise對象的數組 var promises = [2, 3, 5, 7, 11, 13].map(function(id){ return getJSON("/get/addr" + id + ".json"); }); Promise.all(promises).then(function(posts) { // ... }).catch(function(reason){ // ... }); |
Promise.race方法
Promise.race
方法同樣是將多個Promise
實例,包裝成一個新的Promise
實例。
var p = Promise.race([p1,p2,p3]); |
上面代碼中,只要
p1
、p2
、p3
之中有一個實例率先改變狀態,p的狀態就跟著改變。那個率先改變的Promise實例的返回值,就傳遞給p的返回值
如果Promise.all
方法和Promise.race
方法的參數,不是Promise
實例,就會先調用下面講到的Promise.resolve
方法,將參數轉為Promise
實例,再進一步處理
Promise.resolve
有時需要將現有對象轉為
Promise
對象,Promise.resolve
方法就起到這個作用
var jsPromise = Promise.resolve($.ajax('/whatever.json')); |
上面代碼將
jQuery
生成deferred
對象,轉為一個新的ES6
的Promise
對象
如果Promise.resolve
方法的參數,不是具有then
方法的對象(又稱thenable
對象),則返回一個新的Promise
對象,且它的狀態為fulfilled
。
var p = Promise.resolve('Hello'); p.then(function (s){ console.log(s) }); // Hello |
上面代碼生成一個新的Promise
對象的實例p
,它的狀態為fulfilled
,所以回調函數會立即執行,Promise.resolve
方法的參數就是回調函數的參數
如果Promise.resolve
方法的參數是一個Promise
對象的實例,則會被原封不動地返回
Promise.reject(reason)
方法也會返回一個新的Promise
實例,該實例的狀態為rejected
。Promise.reject
方法的參數reason
,會被傳遞給實例的回調函數
var p = Promise.reject('出錯啦'); p.then(null, function (error){ console.log(error) }); // 出錯了 |
function getDataAsync (url) { return new Promise((resolve, reject) => { setTimeout(() => { var res = { url: url, data: Math.random() } resolve(res) }, 1000) }) } |
async function getData ( ) { var res1 = await getDataAsync('/page/1?param=123') console.log(res1) var res2 = await getDataAsync(`/page/2?param=${res1.data}`) console.log(res2) var res3 = await getDataAsync(`/page/2?param=${res2.data}`) console.log(res3) } |
async/await
是基于Promise
的,因為使用async
修飾的方法最終返回一個Promise
, 實際上,async/await
可以看做是使用Generator
函數處理異步的語法糖,我們來看看如何使用Generator
函數處理異步
首先異步函數依然是:
function getDataAsync (url) { return new Promise((resolve, reject) => { setTimeout(() => { var res = { url: url, data: Math.random() } resolve(res) }, 1000) }) } |
使用
Generator
函數可以這樣寫
function * getData ( ) { var res1 = yield getDataAsync('/page/1?param=123') console.log(res1) var res2 = yield getDataAsync(`/page/2?param=${res1.data}`) console.log(res2) var res3 = yield getDataAsync(`/page/2?param=${res2.data}`) console.log(res3)) } |
然后我們這樣逐步執行
var g = getData() g.next().value.then(res1 => { g.next(res1).value.then(res2 => { g.next(res2).value.then(() => { g.next() }) }) }) |
上面的代碼,我們逐步調用遍歷器的
next()
方法,由于每一個next()
方法返回值的value
屬性為一個Promise
對象,所以我們為其添加then
方法, 在then
方法里面接著運行next
方法挪移遍歷器指針,直到Generator
函數運行完成,實際上,這個過程我們不必手動完成,可以封裝成一個簡單的執行器
function run (gen) { var g = gen() function next (data) { var res = g.next(data) if (res.done) return res.value res.value.then((data) => { next(data) }) } next() } |
run
方法用來自動運行異步的Generator
函數,其實就是一個遞歸的過程調用的過程。這樣我們就不必手動執行Generator
函數了。 有了run
方法,我們只需要這樣運行 getData 方法
run(getData) |
這樣,我們就可以把異步操作封裝到
Generator
函數內部,使用run
方法作為Generator
函數的自執行器,來處理異步。其實我們不難發現,async/await
方法相比于Generator
處理異步的方式,有很多相似的地方,只不過async/await
在語義化方面更加明顯,同時async/await
不需要我們手寫執行器,其內部已經幫我們封裝好了,這就是為什么說async/await
是Generator
函數處理異步的語法糖了
Promise
規范有很多,如Promise/A
,Promise/B
,Promise/D
以及 Promise/A
的升級版 Promise/A+
。ES6
中采用了 Promise/A+
規范
中文版規范: Promises/A+規范(中文)
Promise標準解讀
一個promise
的當前狀態只能是pending
、fulfilled
和rejected
三種之一。狀態改變只能是pending
到fulfilled
或者pending
到rejected
。狀態改變不可逆
promise
的then
方法接收兩個可選參數,表示該promise
狀態改變時的回調(promise.then(onFulfilled, onRejected)
)。then
方法返回一個promise
。then
方法可以被同一個 promise
調用多次
構造函數
function Promise(resolver) {} |
原型方法
Promise.prototype.then = function( ) {} Promise.prototype.catch = function( ) {} |
靜態方法
Promise.resolve = function( ) {} Promise.reject = function( ) {} Promise.all = function( ) {} Promise.race = function( ) {} |
function Promise(fn) { var value = null, callbacks = []; //callbacks為數組,因為可能同時有很多個回調 this.then = function (onFulfilled) { callbacks.push(onFulfilled); }; function resolve(value) { callbacks.forEach(function (callback) { callback(value); }); } fn(resolve); } |
大致的邏輯是這樣的
調用then
方法,將想要在Promise
異步操作成功時執行的回調放入callbacks
隊列,其實也就是注冊回調函數,可以向觀察者模式方向思考
創建Promise
實例時傳入的函數會被賦予一個函數類型的參數,即resolve
,它接收一個參數value
,代表異步操作返回的結果,當一步操作執行成功后,用戶會調用resolve
方法,這時候其實真正執行的操作是將callbacks
隊列中的回調一一執行
//例1 function getUserId( ) { return new Promise(function(resolve) { //異步請求 http.get(url, function(results) { resolve(results.id) }) }) } getUserId().then(function(id) { //一些處理 }) |
// 結合例子1分析 // fn 就是getUserId函數 function Promise(fn) { var value = null, callbacks = []; //callbacks為數組,因為可能同時有很多個回調 // 當用戶調用getUserId().then的時候開始注冊傳進來的回調函數 // onFulfilled就是例子中的function(id){} // 把then的回調函數收集起來 在resolve的時候調用 this.then = function (onFulfilled) { callbacks.push(onFulfilled); }; // value是fn函數執行后返回的值 function resolve(value) { // callbacks是傳給then的回調函數就是例子中的function(id){} // 遍歷用戶通過then傳遞進來的回調函數把resolve成功的結果返回給then調用即then(function(data){ console.log(data) }) 這里的data就是通過這里調用返回 callbacks.forEach(function (callback) { callback(value); }); } //執行fn函數即getUserId()并且傳入函數參數resolve 當fn執行完成返回的值傳遞給resolve函數 fn(resolve); } |
結合例1中的代碼來看,首先
new Promise
時,傳給promise
的函數發送異步請求,接著調用promise
對象的then
屬性,注冊請求成功的回調函數,然后當異步請求發送成功時,調用resolve(results.id)
方法, 該方法執行then
方法注冊的回調數組
then
方法應該能夠鏈式調用,但是上面的最基礎簡單的版本顯然無法支持鏈式調用。想讓then
方法支持鏈式調用,其實也是很簡單的
this.then = function (onFulfilled) { callbacks.push(onFulfilled); return this; }; |
只要簡單一句話就可以實現類似下面的鏈式調用
// 例2 getUserId().then(function (id) { // 一些處理 }).then(function (id) { // 一些處理 }); |
上述代碼可能還存在一個問題:如果在
then
方法注冊回調之前,resolve
函數就執行了,怎么辦?比如promise
內部的函數是同步函數
// 例3 function getUserId( ) { return new Promise(function (resolve) { resolve(9876); }); } getUserId().then(function (id) { // 一些處理 }); |
這顯然是不允許的,
Promises/A+
規范明確要求回調需要通過異步方式執行,用以保證一致可靠的執行順序。因此我們要加入一些處理,保證在resolve
執行之前,then
方法已經注冊完所有的回調。我們可以這樣改造下resolve
函數:
function resolve(value) { setTimeout(function( ) { callbacks.forEach(function (callback) { callback(value); }); }, 0) } |
上述代碼的思路也很簡單,就是通過
setTimeout
機制,將resolve
中執行回調的邏輯放置到JS
任務隊列末尾,以保證在resolve
執行時,then
方法的回調函數已經注冊完成
但是,這樣好像還存在一個問題,可以細想一下:如果Promise
異步操作已經成功,這時,在異步操作成功之前注冊的回調都會執行,但是在Promise
異步操作成功這之后調用的then
注冊的回調就再也不會執行了,這顯然不是我們想要的
我們必須加入狀態機制,也就是大家熟知的pending
、fulfilled
、rejected
Promises/A+
規范中的2.1 Promise States
中明確規定了,pending
可以轉化為fulfilled
或rejected
并且只能轉化一次,也就是說如果pending
轉化到fulfilled
狀態,那么就不能再轉化到rejected
。并且fulfilled
和rejected
狀態只能由pending
轉化而來,兩者之間不能互相轉換
//改進后的代碼是這樣的: function Promise(fn) { var state = 'pending', value = null, callbacks = []; this.then = function (onFulfilled) { if (state === 'pending') { callbacks.push(onFulfilled); return this; } onFulfilled(value); return this; }; function resolve(newValue) { value = newValue; state = 'fulfilled'; setTimeout(function ( ) { callbacks.forEach(function (callback) { callback(value); }); }, 0); } fn(resolve); } |
上述代碼的思路是這樣的:
resolve
執行時,會將狀態設置為fulfilled
,在此之后調用then
添加的新回調,都會立即執行
如果用戶在
then
函數里面注冊的仍然是一個Promise
,該如何解決?比如下面的例4
// 例4 getUserId() .then(getUserJobById) .then(function (job) { // 對job的處理 }); function getUserJobById(id) { return new Promise(function (resolve) { http.get(baseUrl + id, function(job) { resolve(job); }); }); } |
這種場景相信用過promise
的人都知道會有很多,那么類似這種就是所謂的鏈式Promise
鏈式Promise
是指在當前promise
達到fulfilled
狀態后,即開始進行下一個promise
(后鄰promise
)。那么我們如何銜接當前promise
和后鄰promise
呢?(這是這里的難點
只要在then
方法里面return
一個promise
就好啦。Promises/A+
規范中的2.2.7
就是這樣
下面來看看這段暗藏玄機的
then
方法和resolve
方法改造代碼
function Promise(fn) { var state = 'pending', value = null, callbacks = []; this.then = function (onFulfilled) { return new Promise(function (resolve) { handle({ onFulfilled: onFulfilled || null, resolve: resolve }); }); }; function handle(callback) { if (state === 'pending') { callbacks.push(callback); return; } //如果then中沒有傳遞任何東西 if(!callback.onFulfilled) { callback.resolve(value); return; } var ret = callback.onFulfilled(value); callback.resolve(ret); } function resolve(newValue) { if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { var then = newValue.then; if (typeof then === 'function') { then.call(newValue, resolve); return; } } state = 'fulfilled'; value = newValue; setTimeout(function ( ) { callbacks.forEach(function (callback) { handle(callback); }); }, 0); } fn(resolve); } |
我們結合例4的代碼,分析下上面的代碼邏輯,為了方便閱讀,我把例4的代碼貼在這里
// 例4 getUserId() .then(getUserJobById) .then(function (job) { // 對job的處理 }); function getUserJobById(id) { return new Promise(function (resolve) { http.get(baseUrl + id, function(job) { resolve(job); }); }); } |
then
方法中,創建并返回了新的Promise
實例,這是串行Promis
e的基礎,并且支持鏈式調用
handle
方法是promise
內部的方法。then
方法傳入的形參onFulfilled
以及創建新Promise
實例時傳入的resolve
均被push
到當前promise
的callbacks
隊列中,這是銜接當前promise
和后鄰promise
的關鍵所在
getUserId
生成的promise
(簡稱getUserId promise
)異步操作成功,執行其內部方法resolve
,傳入的參數正是異步操作的結果id
調用handle
方法處理callbacks
隊列中的回調:getUserJobById
方法,生成新的promise
(getUserJobById promise
)
執行之前由getUserId promise
的then
方法生成的新promise
(稱為bridge promise
)的resolve
方法,傳入參數為getUserJobById promise
。這種情況下,會將該resolve
方法傳入getUserJobById promise
的then
方法中,并直接返回
在getUserJobById promise
異步操作成功時,執行其callbacks
中的回調:getUserId bridge promise
中的resolve
方法
最后執行getUserId bridge promise
的后鄰promise
的callbacks
中的回調
在異步操作失敗時,標記其狀態為
rejected
,并執行注冊的失敗回調
//例5 function getUserId( ) { return new Promise(function(resolve) { //異步請求 http.get(url, function(error, results) { if (error) { reject(error); } resolve(results.id) }) }) } getUserId().then(function(id) { //一些處理 }, function(error) { console.log(error) }) |
有了之前處理
fulfilled
狀態的經驗,支持錯誤處理變得很容易,只需要在注冊回調、處理狀態變更上都要加入新的邏輯
function Promise(fn) { var state = 'pending', value = null, callbacks = []; this.then = function (onFulfilled, onRejected) { return new Promise(function (resolve, reject) { handle({ onFulfilled: onFulfilled || null, onRejected: onRejected || null, resolve: resolve, reject: reject }); }); }; function handle(callback) { if (state === 'pending') { callbacks.push(callback); return; } var cb = state === 'fulfilled' ? callback.onFulfilled : callback.onRejected, ret; if (cb === null) { cb = state === 'fulfilled' ? callback.resolve : callback.reject; cb(value); return; } ret = cb(value); callback.resolve(ret); } function resolve(newValue) { if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { var then = newValue.then; if (typeof then === 'function') { then.call(newValue, resolve, reject); return; } } state = 'fulfilled'; value = newValue; execute(); } function reject(reason) { state = 'rejected'; value = reason; execute(); } function execute( ) { setTimeout(function ( ) { callbacks.forEach(function (callback) { handle(callback); }); }, 0); } fn(resolve, reject); } |
上述代碼增加了新的
reject
方法,供異步操作失敗時調用,同時抽出了resolve
和reject
共用的部分,形成execute
方法
錯誤冒泡是上述代碼已經支持,且非常實用的一個特性。在handle
中發現沒有指定異步操作失敗的回調時,會直接將bridge promise
(then
函數返回的promise
,后同)設為rejected
狀態,如此達成執行后續失敗回調的效果。這有利于簡化串行Promise的失敗處理成本,因為一組異步操作往往會對應一個實際功能,失敗處理方法通常是一致的
//例6 getUserId() .then(getUserJobById) .then(function (job) { // 處理job }, function (error) { // getUserId或者getUerJobById時出現的錯誤 console.log(error); }); |
如果在執行成功回調、失敗回調時代碼出錯怎么辦?對于這類異常,可以使用
try-catch
捕獲錯誤,并將bridge promise
設為rejected
狀態。handle
方法改造如下
function handle(callback) { if (state === 'pending') { callbacks.push(callback); return; } var cb = state === 'fulfilled' ? callback.onFulfilled : callback.onRejected, ret; if (cb === null) { cb = state === 'fulfilled' ? callback.resolve : callback.reject; cb(value); return; } try { ret = cb(value); callback.resolve(ret); } catch (e) { callback.reject(e); } } |
如果在異步操作中,多次執行
resolve
或者reject
會重復處理后續回調,可以通過內置一個標志位解決
// 三種狀態 const PENDING = "pending"; const RESOLVED = "resolved"; const REJECTED = "rejected"; // promise 接收一個函數參數,該函數會立即執行 function MyPromise(fn) { let _this = this; _this.currentState = PENDING; _this.value = undefined; // 用于保存 then 中的回調,只有當 promise // 狀態為 pending 時才會緩存,并且每個實例至多緩存一個 _this.resolvedCallbacks = []; _this.rejectedCallbacks = []; _this.resolve = function (value) { if (value instanceof MyPromise) { // 如果 value 是個 Promise,遞歸執行 return value.then(_this.resolve, _this.reject) } setTimeout(() => { // 異步執行,保證執行順序 if (_this.currentState === PENDING) { _this.currentState = RESOLVED; _this.value = value; _this.resolvedCallbacks.forEach(cb => cb()); } }) }; _this.reject = function (reason) { setTimeout(() => { // 異步執行,保證執行順序 if (_this.currentState === PENDING) { _this.currentState = REJECTED; _this.value = reason; _this.rejectedCallbacks.forEach(cb => cb()); } }) } // 用于解決以下問題 // new Promise(() => throw Error('error)) try { fn(_this.resolve, _this.reject); } catch (e) { _this.reject(e); } } MyPromise.prototype.then = function (onResolved, onRejected) { var self = this; // 規范 2.2.7,then 必須返回一個新的 promise var promise2; // 規范 2.2.onResolved 和 onRejected 都為可選參數 // 如果類型不是函數需要忽略,同時也實現了透傳 // Promise.resolve(4).then().then((value) => console.log(value)) typeof 'function' ? onResolved : v => v; typeof 'function' ? onRejected : r => throw r; if (self.currentState === RESOLVED) { return (promise2 = new MyPromise(function (resolve, reject) { // 規范 2.2.4,保證 onFulfilled,onRjected 異步執行 // 所以用了 setTimeout 包裹下 setTimeout(function ( ) { try { var x = onResolved(self.value); resolutionProcedure(promise2, x, resolve, reject); } catch (reason) { reject(reason); } }); })); } if (self.currentState === REJECTED) { return (promise2 = new MyPromise(function (resolve, reject) { setTimeout(function ( ) { // 異步執行onRejected try { var x = onRejected(self.value); resolutionProcedure(promise2, x, resolve, reject); } catch (reason) { reject(reason); } }); })); } if (self.currentState === PENDING) { return (promise2 = new MyPromise(function (resolve, reject) { self.resolvedCallbacks.push(function ( ) { // 考慮到可能會有報錯,所以使用 try/catch 包裹 try { var x = onResolved(self.value); resolutionProcedure(promise2, x, resolve, reject); } catch (r) { reject(r); } }); self.rejectedCallbacks.push(function ( ) { try { var x = onRejected(self.value); resolutionProcedure(promise2, x, resolve, reject); } catch (r) { reject(r); } }); })); } }; // 規范 2.3 function resolutionProcedure(promise2, x, resolve, reject) { // 規范 2.3.1,x 不能和 promise2 相同,避免循環引用 if (promise2 === x) { return reject(new TypeError("Error")); } // 規范 2.3.2 // 如果 x 為 Promise,狀態為 pending 需要繼續等待否則執行 if (x instanceof MyPromise) { if (x.currentState === PENDING) { x.then(function (value) { // 再次調用該函數是為了確認 x resolve 的 // 參數是什么類型,如果是基本類型就再次 resolve // 把值傳給下個 then resolutionProcedure(promise2, value, resolve, reject); }, reject); } else { x.then(resolve, reject); } return; } // 規范 2.3.3.3.3 // reject 或者 resolve 其中一個執行過得話,忽略其他的 let called = false; // 規范 2.3.3,判斷 x 是否為對象或者函數 if (x !== null && (typeof x === "object" || typeof x === "function")) { // 規范 2.3.3.2,如果不能取出 then,就 reject try { // 規范 2.3.3.1 let then = x.then; // 如果 then 是函數,調用 x.then if (typeof then === "function") { // 規范 2.3.3.3 then.call( x, y => { if (called) return; called = true; // 規范 2.3.3.3.1 resolutionProcedure(promise2, y, resolve, reject); }, e => { if (called) return; called = true; reject(e); } ); } else { // 規范 2.3.3.4 resolve(x); } } catch (e) { if (called) return; called = true; reject(e); } } else { // 規范 2.3.4,x 為基本類型 resolve(x); } } |
這里一定要注意的點是:promise
里面的then
函數僅僅是注冊了后續需要執行的代碼,真正的執行是在resolve
方法里面執行的,理清了這層,再來分析源碼會省力的多
現在回顧下
Promise
的實現過程,其主要使用了設計模式中的觀察者模式
通過Promise.prototype.then
和Promise.prototype.catch
方法將觀察者方法注冊到被觀察者Promise
對象中,同時返回一個新的Promise
對象,以便可以鏈式調用
被觀察者管理內部pending
、fulfilled
和rejected
的狀態轉變,同時通過構造函數中傳遞的resolve
和reject
方法以主動觸發狀態轉變和通知觀察者
到此,關于“Promise的原理和基礎用法介紹”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。