摘要:意味著操作成功完成。狀態(tài)的對象可能觸發(fā)狀態(tài)并傳遞一個值給相應的狀態(tài)處理方法,也可能觸發(fā)失敗狀態(tài)并傳遞失敗信息。測試用例測試用例方法返回一個帶有拒絕原因參數(shù)的對象。
Promise基本用法
Promise 對象是一個代理對象,被代理的值在Promise對象創(chuàng)建時可能是未知的。
它允許你為異步操作的成功和失敗分別綁定相應的處理方法(handlers)。 這讓異步方法可以像同步方法那樣返回值,但并不是立即返回最終執(zhí)行結果,而是一個能代表未來出現(xiàn)的結果的promise對象
一個 Promise有以下幾種狀態(tài):
pending: 初始狀態(tài),既不是成功,也不是失敗狀態(tài)。 fulfilled: 意味著操作成功完成。 rejected: 意味著操作失敗。
pending 狀態(tài)的 Promise 對象可能觸發(fā)fulfilled 狀態(tài)并傳遞一個值給相應的狀態(tài)處理方法,也可能觸發(fā)失敗狀態(tài)(rejected)并傳遞失敗信息。當其中任一種情況出現(xiàn)時,Promise 對象的 then 方法綁定的處理方法(handlers )就會被調用(then方法包含兩個參數(shù):onfulfilled 和 onrejected,它們都是 Function 類型。當Promise狀態(tài)為fulfilled時,調用 then 的 onfulfilled 方法,當Promise狀態(tài)為rejected時,調用 then 的 onrejected 方法, 所以在異步操作的完成和綁定處理方法之間不存在競爭)。
因為 Promise.prototype.then 和 Promise.prototype.catch 方法返回promise 對象, 所以它們可以被鏈式調用。
var promise1 = new Promise(function(resolve, reject) { setTimeout(function() { resolve("foo"); }, 300); }); promise1.then(function(value) { console.log(value); // expected output: "foo" }); console.log(promise1); // expected output: [object Promise]Promise/A+
然后我們來了解一下Promise規(guī)范
Promises/A+規(guī)范(英文版)
Promises/A+規(guī)范(中文版)
Promise是通過new創(chuàng)建的,可以通過構造函數(shù)模式或者是ES6的class來實現(xiàn),這兒選擇構造函數(shù)的方式來實現(xiàn)Promise,首先先完成一個簡易版本的Promise。
function Promise(exector) { var _this = this this.status = "pending" this.value = undefined try { exector(resolve, reject) }catch(e) { reject(e) } function resolve(value) { if(_this.status === "pending") { _this.status = "fulfilled" _this.value = value } } function reject(value) { if(_this.status === "pending") { _this.status = "rejected" _this.value = value } } } Promise.prototype.then = function(resolveCallback, rejectCallback) { if(this.status === "fulfilled") { resolve(this.value) } if(this.status === "rejected") { reject(this.value) } } new Promise((resolve, reject)=> { resolve("1") }).then((data)=> { console.log("resolve" + data) }, (data)=> { console.log("reject" + data) }) //resolve1 new Promise((resolve, reject)=> { setTimeout(()=> { resolve("1") }, 1000) }).then((data)=> { console.log("resolve" + data) }, (data)=> { console.log("reject" + data) }) //無法正常輸出
上面這個promise中resolve和reject在同步的情況下都能正常輸出,但是現(xiàn)在卻不支持異步,因為在異步的時候調用then的時候狀態(tài)還是"pending",所以resolve/reject并不能如期執(zhí)行。
這個時候就需要一個存放后續(xù)調用事件的數(shù)組,當異步函數(shù)執(zhí)行完畢后再執(zhí)行數(shù)組中的函數(shù)。
改進后異步方法可以正常運行:
function Promise(exector) { var _this = this this.status = "pending" this.value = undefined this.resolveList = [] this.rejectList = [] try { exector(resolve, reject) }catch(e) { reject(e) } function resolve(value) { if(_this.status === "pending") { _this.status = "fulfilled" _this.value = value _this.resolveList.forEach(item=> { item(_this.value) _this.resolveList.shift() }) } } function reject(value) { if(_this.status === "pending") { _this.status = "rejected" _this.value = value _this.rejectList.forEach(item=> { item(_this.value) _this.rejectList.shift() }) } } } Promise.prototype.then = function(resolveCallback, rejectCallback) { if(this.status === "fulfilled") { resolve(this.value) } if(this.status === "rejected") { reject(this.value) } if(this.status === "pending") { this.resolveList.push(resolveCallback) this.rejectList.push(rejectCallback) } } new Promise((resolve, reject)=> { setTimeout(()=> { resolve("1") }, 1000) }).then((data)=> { console.log("resolve" + data) }, (data)=> { console.log("reject" + data) })鏈式調用
我們可以注意到Promise是可以鏈式調用的,這就需要then的方法返回一個Promise對象。
下面是一個鏈式調用的簡單例子:
let promise = new Promise((resolve, reject)=> { resolve(666) }) promise.then(data=> { console.log(data) return data + 1 }).then(data=> { console.log(data) }) //666 //667
在Promise鏈中返回Promise:
let promise1 = new Promise((resolve, reject)=> { resolve(666) }) let promise2 = new Promise((resolve, reject)=> { resolve(999) }) promise1.then(data=> { console.log(data) return promise2 }).then(data=> { console.log(data) }) //666 //999
關于這種寫法需要注意的是,第二個完成處理程序被添加到第三個promise而不是return的promise2,上面的例子等價于:
let promise1 = new Promise((resolve, reject)=> { resolve(666) }) let promise2 = new Promise((resolve, reject)=> { resolve(999) }) let promise3 = promise1.then(data=> { console.log(data) return promise2 }) promise3.then(data=> { console.log(data) }) //666 //999
當異步的時候調用then函數(shù)的時候狀態(tài)為pending,這個時候同樣需要返回一個promise方便后續(xù)的鏈式調用。
所以修改為鏈式調用后的代碼為:
function Promise(exector) { var _this = this this.status = "pending" this.value = undefined this.resolveList = [] this.rejectList = [] try { exector(resolve, reject) }catch(e) { reject(e) } function resolve(value) { if(_this.status === "pending") { _this.status = "fulfilled" _this.value = value _this.resolveList.forEach(item=> { item(_this.value) _this.resolveList.shift() }) } } function reject(value) { if(_this.status === "pending") { _this.status = "rejected" _this.value = value _this.rejectList.forEach(item=> { item(_this.value) _this.rejectList.shift() }) } } } Promise.prototype.then = function(resolveCallback, rejectCallback) { var _this = this if(this.status === "fulfilled") { return new Promise((resolve, reject)=> { var result = resolveCallback(_this.value) if(result instanceof Promise) { result.then(resolve, reject) }else { resolve(result) } }) } if(this.status === "rejected") { return new Promise((resolve, reject)=> { var result = rejectCallback(_this.value) if(result instanceof Promise) { result.then(resolve, reject) }else { reject(result) } }) } if(this.status === "pending") { return new Promise((resolve, reject)=> { _this.resolveList.push(function() { var result = resolveCallback(_this.value) if(result instanceof Promise) { result.then(resolve, reject) }else { resolve(result) } }) _this.rejectList.push(function() { var result = rejectCallback(_this.value) if(result instanceof Promise) { result.then(resolve, reject) }else { reject(result) } }) }) } } new Promise((resolve, reject)=> { resolve(666) }).then((data)=> { console.log("resolve1:" + data) return 999 }).then((data)=> { console.log("resolve2:" + data) }) //resolve1: 666 //resolve2: 999 new Promise((resolve, reject)=> { resolve(666) }).then((data)=> { console.log("resolve1:" + data) return new Promise((resolve, reject)=> { resolve(999) }) }).then((data)=> { console.log("resolve2:" + data) }) //resolve1: 666 //resolve2: 999
基本的功能已經實現(xiàn),下面開始實現(xiàn)Promise的all,race,resolve,reject方法,鏈式調用部分思路借鑒Promise/A+規(guī)范的實現(xiàn)
Promise.all()該方法只接受一個有多個受監(jiān)聽的Promise的可迭代對象(比如數(shù)組),只有當可迭代對中所有Promise都被解決后才會返回resolve,如果參數(shù)中 promise 有一個失敗,此實例回調失敗(reject),失敗原因的是第一個失敗 promise 的結果。
Promise.all = function(iterable) { return new Promise((resolve, reject) => { let result = [] for(const item of iterable) { item.then(data => { result.push(data) }, reason=> { result = reason return }) } resolve(result) }) } //下面是測試用例 let p1 = new Promise((resolve, reject) => { resolve(666) }) let p2 = new Promise((resolve, reject) => { resolve(888) }) let p3 = new Promise((resolve, reject) => { resolve(999) }) let p6 = new Promise((resolve, reject) => { reject(222) }) let p4 = Promise.all([p1, p2, p3]) p4.then(data => { console.log(data) }) //[666, 888, 999] let p7 = Promise.all([p1, p3, p6]) p7.then(data => { console.log(data) }) //222Promise.race()
Promise.race(iterable) 方法返回一個 promise,一旦迭代器中的某個promise解決或拒絕,返回的 promise就會解決或拒絕。
Promise.race = function(iterable) { return new Promise((resolve, reject) => { for(const item of iterable) { item.then(data => { resolve(data) }, reason=> { reject(reson) }) } }) } //測試用例 var p1 = new Promise(function(resolve, reject) { setTimeout(resolve, 500, "one"); }); var p2 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, "two"); }); Promise.race([p1, p2]).then(function(value) { console.log(value); // Both resolve, but promise2 is faster }); //twoPromise.resolve()
Promise.resolve = function(data) { return new Promise((resolve, reject) => { resolve(data) }) } //測試用例 var p1 = Promise.resolve(123); p1.then(function(value) { console.log(value); }); //123Promise.reject()
Promise.reject(reason)方法返回一個帶有拒絕原因reason參數(shù)的Promise對象。
Promise.resolve = function(data) { return new Promise((resolve, reject) => { reject(data) }) }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/108992.html
摘要:它之后能夠被使用到很多場景中其他處理請求和響應的方式,甚至任何需要生成自己的響應的方式??偨Y到這里都講完了,其實沒什么難度,主要是自己項目中遇到了,但是中沒有這個方法啊。所以就想著實現(xiàn)了一個,因為其他的方法也都封裝,不差這一個了。 Fetch 提供了對?Request?和?Response?(以及其他與網絡請求有關的)對象通用的定義。它之后能夠被使用到很多場景中:service wor...
摘要:一個后可以通過方法,指定和時的回調函數(shù)。構造函數(shù)內部要有一個值,用來保存上次執(zhí)行的結果值,如果報錯,則保存的是異常信息。因為是一個構造函數(shù),使用的寫法,首先想到的就是有顯式聲明的。 showImg(https://segmentfault.com/img/bVbffEu?w=530&h=253); Javascript語言的執(zhí)行環(huán)境是單線程(single thread)。所謂單線程,就...
摘要:一個后可以通過方法,指定和時的回調函數(shù)。構造函數(shù)內部要有一個值,用來保存上次執(zhí)行的結果值,如果報錯,則保存的是異常信息。因為是一個構造函數(shù),使用的寫法,首先想到的就是有顯式聲明的。 showImg(https://segmentfault.com/img/bVbffEu?w=530&h=253); Javascript語言的執(zhí)行環(huán)境是單線程(single thread)。所謂單線程,就...
摘要:解析原理,實現(xiàn)一個概述這篇文章旨在解析的異步實現(xiàn)原理,并且以中的為藍本實現(xiàn)一個簡單的。具體的規(guī)范可以參見細節(jié)構造器中必須傳入函數(shù),否則會拋出錯誤。中的回調返回值會影響返回的對象。執(zhí)行器傳入構造器的為函數(shù),并且在構造時就會執(zhí)行。 解析 Promise 原理,實現(xiàn)一個Promise 概述 這篇文章旨在解析 Promise的異步實現(xiàn)原理,并且以 ES6中的 Promise 為藍本實現(xiàn)一個簡單...
閱讀 2210·2021-11-22 13:54
閱讀 3375·2019-08-29 12:25
閱讀 3439·2019-08-28 18:29
閱讀 3578·2019-08-26 13:40
閱讀 3275·2019-08-26 13:32
閱讀 954·2019-08-26 11:44
閱讀 2227·2019-08-23 17:04
閱讀 2967·2019-08-23 17:02