来,一起来实现一个符合Promise/A+的Promose(1.0.1版本)
Promose是什么?(必要的科普)
為解決異步函數的回調陷阱,開發社區不斷摸索,終于折騰出 Promise/A+。它的優勢非常顯著:
這套方案在迭代中逐步完善,最終被吸收進 ES2015。不僅如此,ES2017 中還增加了 Await/Async,可以用順序的方式書寫異步代碼,甚至可以正常拋出捕獲錯誤,維護同一個棧??梢哉f徹底解決了異步回調的問題。
現在大部分瀏覽器和 Node.js 都已原生支持 Promise,很多類庫也開始返回 Promise 對象,更有各種降級適配策略。Node.js 7+ 則實裝了 Await/Async。
Promose的基本用法
let Mypromise = require('./Promise') // 這個是自己寫的 Promise 函數 底下有代碼講解 let p1 = new Mypromise(function(resolve,reject){resolve('666') }) p1.then(function(data){console.log(data) },function(err){console.log(err) })復制代碼Promise 是一個代理對象,它和原先的異步操作并無關系。它接受一個“執行器 executor”作為參數,我們把原先要執行的異步(并非一定要異步,以后會說明,這里你可以先不深究)操作放進去。
執行器在 Promise 實例創建后立刻開始執行。執行器自帶兩個參數:resolve 和 reject,這二位都是函數,執行它們會改變 Promise 實例的狀態。
Promise 實例有三個狀態:
Promise 實例狀態改變之后,就會觸發后面對應的 .then() 參數里的函數,繼續執行后續步驟。另外,Promise 的實例狀態只會改變一次,確定為 fulfilled 或 rejected 之一后就不會再變。
我們來看看??Promise函數方面代碼要怎么實現:
function Promise(executor) { // executor是一個執行函數let self = this; // 緩存this 防止出錯 self.status = 'pending'; // 初始化狀態self.value = undefined; // 默認成功的值self.reason = undefined; // 默認失敗的原因function resolve(value) { // 成功狀態if (self.status === 'pending') { // 判斷當前當前狀態self.status = 'resolved'; // 把pending 狀態變成 成功的狀態 resolvedself.value = value; // 給默認成功狀態 賦值}}function reject(reason) { // 失敗狀態if (self.status === 'pending') { // 判斷 Promise 當前狀態 如果是初始化 self.status = 'rejected'; // pending 狀態變成 失敗的狀態 rejectedself.reason = reason; // 給默認失敗的原因賦值}}try {executor(resolve, reject)} catch (e) { // 捕獲執行的時候發生異常,就直接失敗了 當 new 一個 新的 Promise對象 拋出一個錯誤時候// 如 在 Promise實例里 throw new Error('錯誤了')reject(e);} }Promise.prototype.then = function(onFulfilled, onReject){ let self = this; if(self.status === 'resolved'){ // onFulfilled(self.value)}if(self.status === 'rejected'){onReject(self.reason)} } module.exports = Promise;復制代碼以上是Promise最基本的實現
我們來試試看運行結果: 當Primose 實例狀態為 resolve(成功)的時候,顯示結果如下
接下來測試下:??當Primose 實例狀態為 reject(失敗)的時候 顯示如下
從代碼結果來看,現在Promise 函數 內部的 ‘ pedding’ 狀態 已經可以 根據 成功和數百的狀態來改變了?
當如果兩個函數同時運行呢!!!如下?
只會顯示一個結果 誰先執行 狀態就變成誰 不會 同時 執行兩個結果??
現在我們已經初步實現了 Promise 函數 的同步方法了?
接下來繼續 實現其他的 如(多次then ,異步,Promise (then返回一個新的Promise對象))
定義兩個接收 成功的數組 和失敗的數組 如下:
function Promise(executor) { // executor是一個執行函數let self = this;self.status = 'pending';self.value = undefined; // 默認成功的值self.reason = undefined; // 默認失敗的原因self.onResolvedCallbacks = []; // 存放then成功的回調self.onRejectedCallbacks = []; // 存放then失敗的回調function resolve(value) { // 成功狀態if (self.status === 'pending') {self.status = 'resolved';self.value = value;// 當成功以后, 依次執行成功數組里面的函數self.onResolvedCallbacks.forEach(function (fn) {fn();});}}function reject(reason) { // 失敗狀態if (self.status === 'pending') {self.status = 'rejected';self.reason = reason;// 當失敗以后, 依次執行失敗數組里面的函數self.onRejectedCallbacks.forEach(function (fn) {fn();})}}try {executor(resolve, reject)} catch (e) { // 捕獲的時候發生異常,就直接失敗了reject(e);} }復制代碼然后在 then方法中也需要判斷當前的狀態? ?如果是?pending則需要做下處理
Promise.prototype.then = function(onFulfilled, onReject){let self = this;if(self.status === 'resolved'){ //onFulfilled(self.value)}if(self.status === 'rejected'){onReject(self.reason)}// 當調用then時可能沒成功 也沒失敗 if (self.status === 'pending') {// 此時沒有 resolve 也沒有 rejectself.onResolvedCallbacks.push(function(){onFulfilled(self.value)})self.onRejectedCallbacks.push(function(){onReject(self.reason)})} }復制代碼執行實例代碼: 結果如下
用了兩次 then : 顯示都成功了? 調用多少次then 就顯示多少個成功
實例代碼如下:
let p = new Promise(function(resolve,reject){resolve(); }) let p2 = p.then(function(){throw new Error('錯誤'); }) p2.then(function(){ // 可以返回一個新的 Promise },function(err){console.log(err); // 這邊輸出錯誤 })復制代碼代碼如下:
Promise.prototype.then = function(onFulfilled, onReject){let self = this;let promise2; //返回的promiseif (self.status === 'resolved') {promise2 = new Promise(function (resolve, reject) {try{onFulfilled(self.value);}catch (e){reject(e)}})}if (self.status === 'rejected') {promise2 = new Promise(function (resolve, reject) {try{onReject(self.reason)}catch (e){reject(e)}})}// 當調用then時可能沒成功 也沒失敗if (self.status === 'pending') {promise2 = new Promise(function (resolve, reject) {// 此時沒有resolve 也沒有rejectself.onResolvedCallbacks.push(function () {try{onFulfilled(self.value)}catch (e){reject(e)}});self.onRejectedCallbacks.push(function () {try{onReject(self.reason)}catch (e){reject(e)}});})}return promise2; }復制代碼如果第一個promise返回一個普通值,會進到下一次then的成功的回調,如果第一個promise返回了一個promise,需要等待返回的promise執行后的結果傳遞給下一次then中let p1 = new Promise(function(resolve,reject){resolve('333') }) p1.then(function(data){return new Promise(function(resolve,reject){setTimeout(function () {resolve(100)},1000)}) },function(err){throw new Error('失敗') }).then(function (data) {console.log(data) },function (err) {console.log(err) })復制代碼
接下來實現?resolvePromise 函數
function resolvePromise(promise2, x, resolve, reject) {// 有可能這里返回的x是別人的promise// 盡可能允許其他亂寫if (promise2 === x) { //這里應該報一個類型錯誤,有問題return reject(new TypeError('循環引用了'))}// 看x是不是一個promise,promise應該是一個對象let called; // 表示是否調用過成功或者失敗if (x !== null && (typeof x === 'object' || typeof x === 'function')) {// 可能是promise {},看這個對象中是否有then方法,如果有then我就認為他是promise了try { // {then:1}let then = x.then;if (typeof then === 'function') {// 成功then.call(x, function (y) {if (called) returncalled = true// y可能還是一個promise,在去解析直到返回的是一個普通值resolvePromise(promise2, y, resolve, reject)}, function (err) { //失敗if (called) returncalled = truereject(err);})} else {resolve(x)}} catch (e) {if (called) returncalled = true;reject(e);}} else { // 說明是一個普通值1resolve(x); // 表示成功了} }復制代碼快速實現常用的其他 Promise 方法:// 捕獲錯誤的方法 Promise.prototype.catch = function (callback) {return this.then(null, callback) } // 解析全部方法 Promise.all = function (promises) {//promises是一個promise的數組return new Promise(function (resolve, reject) {let arr = []; //arr是最終返回值的結果let i = 0; // 表示成功了多少次function processData(index, y) {arr[index] = y;if (++i === promises.length) {resolve(arr);}}for (let i = 0; i < promises.length; i++) {promises[i].then(function (y) {processData(i, y)}, reject)}}) } // 只要有一個promise成功了 就算成功。如果第一個失敗了就失敗了 Promise.race = function (promises) {return new Promise(function (resolve, reject) {for (var i = 0; i < promises.length; i++) {promises[i].then(resolve,reject)}}) } // 生成一個成功的promise Promise.resolve = function(value){return new Promise(function(resolve,reject){resolve(value);}) } // 生成一個失敗的promise Promise.reject = function(reason){return new Promise(function(resolve,reject){reject(reason);}) } Promise.defer = Promise.deferred = function () {let dfd = {};dfd.promise = new Promise(function (resolve, reject) {dfd.resolve = resolve;dfd.reject = reject;});return dfd }復制代碼寫在結尾: 第一次寫文章,邏輯有點亂,希望能幫上大家,大家不要噴,有什么錯誤,請指出,很感謝!肯定會重寫寫一遍,更好的給大家
總結
以上是生活随笔為你收集整理的来,一起来实现一个符合Promise/A+的Promose(1.0.1版本)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: idea maven dependenc
- 下一篇: rabbitmq中文教程python版