成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

一步步寫一個(gè)符合Promise/A+規(guī)范的庫(kù)

econi / 3011人閱讀

摘要:本意是承諾,在程序中的意思就是承諾我過一段時(shí)間后會(huì)給你一個(gè)結(jié)果。中采用了規(guī)范,實(shí)現(xiàn)之前,當(dāng)然要先了解規(guī)范,規(guī)范地址。我們根據(jù)規(guī)范,可以寫一個(gè)簡(jiǎn)單的庫(kù)。每一步都盡量寫的詳細(xì),所以代碼很長(zhǎng)很羅嗦。

Promise本意是承諾,在程序中的意思就是承諾我過一段時(shí)間后會(huì)給你一個(gè)結(jié)果。

ES6 中采用了 Promise/A+ 規(guī)范,Promise 實(shí)現(xiàn)之前,當(dāng)然要先了解 Promise/A+ 規(guī)范,規(guī)范地址https://promisesaplus.com/。

我們根據(jù) Promise/A+ 規(guī)范,可以寫一個(gè)簡(jiǎn)單的Promise庫(kù)。

每一步都盡量寫的詳細(xì),所以代碼很長(zhǎng)很羅嗦。

1.實(shí)現(xiàn)Promise基本的方法

Promise是一個(gè)類,需要傳遞一個(gè)executor函數(shù),函數(shù)里有兩個(gè)參數(shù)resolve和reject,調(diào)用resolve代表成功,調(diào)用reject代表失敗

Promise有三種狀態(tài):默認(rèn)狀態(tài)是等待狀態(tài)pending,成功resolved,失敗rejected

使用例子
let Promise = require("./Promise");
// Promise是一個(gè)類,需要傳遞一個(gè)executor函數(shù),這個(gè)函數(shù)我們稱之為執(zhí)行函數(shù),函數(shù)中有兩個(gè)參數(shù)resolve和reject他們也是函數(shù),調(diào)用resolve表示成功,調(diào)用reject表示失敗
let promise = new Promise(function(resolve,reject){
    // 成功就不會(huì)再調(diào)用失敗,默認(rèn)狀態(tài)是等待狀態(tài)pending
    resolve("ok"); 
    reject("faild");
});
// then是原型上的一個(gè)方法接收兩個(gè)參數(shù)分別是成功的回調(diào)和失敗的回調(diào)
promise.then(function(data){// 調(diào)用resolve后會(huì)執(zhí)行成功的回調(diào),調(diào)用reject后會(huì)執(zhí)行失敗的回調(diào)
    console.log(data);
},function(err){
    console.log(err);
});
實(shí)現(xiàn)對(duì)應(yīng)的Promise庫(kù)代碼
function Promise(executor) {  // Promise中需要接收一個(gè)執(zhí)行函數(shù)executor
    let self = this;
    self.status = "pending"; //默認(rèn)是pending狀態(tài)
    self.value = undefined; // 成功的原因
    self.reason = undefined; // 失敗的原因
    function resolve(value) { // 調(diào)用resolve 會(huì)傳入為什么成功
        if(self.status === "pending"){ // 只有再pending才能轉(zhuǎn)換成功態(tài)
            self.value = value; // 將成功的原因保存下來
            self.status = "resolved"; // 狀態(tài)改成成功態(tài) 
        }
    }
    function reject(reason) { // 調(diào)用reject會(huì)傳入為什么失敗
        if(self.status === "pending"){
            self.reason = reason;
            self.status = "rejected";
        }
    }
    try {
        executor(resolve, reject);// executor中需要傳入resolve和reject
    } catch (e) {
        // 如果executor執(zhí)行發(fā)生異常,表示當(dāng)前的promise是失敗態(tài)
        reject(e);
    }
}
// then中要傳入成功的回調(diào)和失敗的回調(diào)
Promise.prototype.then = function(onFufilled,onRejected){
    let self = this;
    // 如果要是成功就調(diào)用成功的回調(diào),并將成功的值傳入
    if(self.status === "resolved"){
        onFufilled(self.value);
    }
    if(self.status === "rejected"){
        onRejected(self.reason);
    }
}
module.exports = Promise
2.異步Promise

在new Promise時(shí)內(nèi)部可以寫異步代碼,并且產(chǎn)生的實(shí)例可以then多次

用兩個(gè)數(shù)組存放成功和失敗的回調(diào),當(dāng)調(diào)用的時(shí)候再執(zhí)行

使用例子
let Promise = require("./Promise");
let promise = new Promise(function(resolve,reject){
    setTimeout(function(){
        resolve("ok");
    },1000)
});
// 當(dāng)調(diào)用then時(shí)可能狀態(tài)依然是pending狀態(tài),我們需要將then中的回調(diào)函數(shù)保留起來,當(dāng)調(diào)用resolve或者reject時(shí)按照順序執(zhí)行
promise.then(function(data){
    console.log(data);
},function(err){
    console.log(err);
});
promise.then(function(data){
    console.log(data);
},function(err){
    console.log(err);
});
實(shí)現(xiàn)對(duì)應(yīng)的Promise庫(kù)代碼
function Promise(executor) {  
     self.status = "pending"; 
     self.value = undefined; 
     self.reason = undefined; 
+    self.onResolvedCallbacks = []; // 成功回調(diào)存放的地方
+    self.onRejectedCallbacks = [];// 失敗回調(diào)存放的地方
     function resolve(value) { 
         if(self.status === "pending"){ 
             self.value = value; 
             self.status = "resolved"; 
+            // 依次執(zhí)行成功的回調(diào)
+            self.onResolvedCallbacks.forEach(item=>item());
         }
     }
     function reject(reason) {
         if(self.status === "pending"){
             self.reason = reason;
             self.status = "rejected";
+            // 依次執(zhí)行失敗的回調(diào)
+            self.onRejectedCallbacks.forEach(item=>item());
         }
     }
}
Promise.prototype.then = function(onFufilled,onRejected){
     if(self.status === "rejected"){
         onRejected(self.reason);
     }
+    if(self.status === "pending"){
+        // 如果是等待態(tài),就將成功和失敗的回調(diào)放到數(shù)組中
+        self.onResolvedCallbacks.push(function(){
+            onFufilled(self.value);
+        });
+        self.onRejectedCallbacks.push(function(){
+            onRejected(self.reason);
+        });
+    }
 }
3.Promise鏈?zhǔn)秸{(diào)用

如果當(dāng)前promise已經(jīng)進(jìn)入成功的回調(diào),回調(diào)中發(fā)生了異常返回this的話,那么當(dāng)前的promise的狀態(tài)無法更改到失敗臺(tái)!所以promise實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用,返回的并不是this而是一個(gè)新的promise。

執(zhí)行回調(diào)中

如果返回的是一個(gè)普通的值,會(huì)將結(jié)果傳入下一次then的成功回調(diào)中

如果發(fā)生錯(cuò)誤會(huì)被下一次then的失敗回調(diào)捕獲

如果返回的是promise看這個(gè)promise是成功還是失敗,對(duì)應(yīng)調(diào)用下一次的then

所以寫一個(gè)resolvePromise方法,這是promise中最重要的方法,用來解析then返回的結(jié)果

有些人可能成功失敗同時(shí)調(diào)用,如果兩個(gè)都調(diào)用,用第一個(gè)調(diào)用的,不允許同時(shí)調(diào)用。

使用例子
promise.then(function(data){
    throw Error("出錯(cuò)了");// 當(dāng)前promise已經(jīng)成功了,成功就不會(huì)再失敗
    return "renee" 
}).then(null,function(err){ // 如果返回的是同一個(gè)promise那么還怎么走向失敗呢?所以必須要返回一個(gè)新的promise
    console.log(err);
})
實(shí)現(xiàn)對(duì)應(yīng)的Promise庫(kù)代碼
 Promise.prototype.then = function(onFufilled,onRejected){
     let self = this;
+    let promise2; // promise2為then調(diào)用后返回的新promise
     // 如果要是成功就調(diào)用成功的回調(diào),并將成功的值傳入
     if(self.status === "resolved"){
-        onFufilled(self.value);
+        promise2 = new Promise(function(resolve,reject){
+            try{
+                // 執(zhí)行時(shí)有異常發(fā)生,需要將promise2的狀態(tài)置為失敗態(tài)
+                let x = onFufilled(self.value); 
+                // x為返回的結(jié)果
+                // 寫一個(gè)方法resolvePromise,是對(duì)當(dāng)前返回值進(jìn)行解析,通過解析讓promise2的狀態(tài)轉(zhuǎn)化成成功態(tài)還是失敗態(tài)
+                resolvePromise(promise2,x,resolve,reject);
+            }catch(e){
+                reject(e);
+            }
+        })
     }
     if(self.status === "rejected"){
-        onRejected(self.reason);
+        promise2 = new Promise(function(resolve,reject){
+            try{
+                let x = onRejected(self.reason);
+                resolvePromise(promise2,x,resolve,reject);
+            }catch(e){
+                reject(e)
+            }
+        })
     }
     if(self.status === "pending"){
+       promise2 = new Promise(function(resolve,reject){
         self.onResolvedCallbacks.push(function(){
-            onFufilled(self.value);
+                try{
+                    let x = onFufilled(self.value);
+                    resolvePromise(promise2,x,resolve,reject)
+                }catch(e){
+                    reject(e);
+                }
+            })
         });
         self.onRejectedCallbacks.push(function(){
-            onRejected(self.reason);
+                try{
+                    let x = onRejected(self.reason);
+                    resolvePromise(promise2,x,resolve,reject)
+                }catch(e){
+                    reject(e);
+                }
         });
+       })
     }
+    return promise2;
 }
function resolvePromise(promise2, x, resolve, reject) {
    //x是返回的結(jié)果,如果promise和then中返回的promise是同一個(gè),是不科學(xué)的,要報(bào)錯(cuò)
    if(promise2===x){
        return reject(new Error("循環(huán)引用"))
    }
    if(x!==null&&(typeof x === "object"|| typeof x === "function")){
        let called; //表示是否調(diào)用過成功或者失敗
        try{
            let then=x.then;
            //如果then是函數(shù),說明是promise,我們要讓promise執(zhí)行
            if(typeof then==="function"){
                then.call(x,function(y){
                    if(called)return; //如果調(diào)用過直接return
                    called=true;
                    //如果resolve的結(jié)果依舊是promise那就繼續(xù)解析
                },function(err){
                    if(called) return;
                    called=true;
                    reject(err)
                })
            }else{//如果不是函數(shù),x是一個(gè)普通的對(duì)象,直接成功即可
                resolve(x)
            }
        }catch(e){
            if(called) return;
            called=true;
            reject(e);
        }
    }else{
        //是普通值直接調(diào)用成功
        resolve(x);
    }
}
4.值的穿透

在規(guī)范中定義then函數(shù)可以不傳參,不傳參默認(rèn)會(huì)將成功的結(jié)果和失敗的結(jié)果繼續(xù)向下傳遞

使用例子
promise.then().then().then(function(data){
  console.log(data)
})
實(shí)現(xiàn)對(duì)應(yīng)的Promise庫(kù)代碼
Promise.prototype.then = function (onFufilled, onRejected) {
  //失敗和成功默認(rèn)不傳給一個(gè)函數(shù)
+    onFufilled = typeof onFufilled === "function"?onFufilled:function(value){
+        return value
+    }
+    onRejected = typeof onRejected === "function"?onRejected:function(err){
+        throw err
+    }
5.測(cè)試

另外可以通過安裝一個(gè)插件來對(duì)實(shí)現(xiàn)的promise進(jìn)行規(guī)范測(cè)試。

npm(cnpm) i -g promises-aplus-tests
promises-aplus-tests 文件名

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/93498.html

相關(guān)文章

  • 個(gè)符合A+規(guī)范Promise

    摘要:本文同時(shí)也發(fā)布在我的博客上,歡迎之前也手寫過簡(jiǎn)單的,這次則是為了通過官方的測(cè)試集,借鑒了一些下載量較多的,改了幾遍,終于是通過了規(guī)范的個(gè)測(cè)試用例如何測(cè)試測(cè)試庫(kù)地址在這,大家在寫完自己的后,不妨也去測(cè)試一下,檢驗(yàn)自己的是否符合規(guī)范。 本文同時(shí)也發(fā)布在我的github博客上,歡迎star~ 之前也手寫過簡(jiǎn)單的promise,這次則是為了通過官方的Promise A+測(cè)試集,借鑒了一些下載量...

    jsummer 評(píng)論0 收藏0
  • 個(gè)符合promiseA+規(guī)范promise實(shí)現(xiàn)

    摘要:如何寫一個(gè)符合規(guī)范的實(shí)現(xiàn)前言是異步編程的一種解決方案從語法上講,是一個(gè)對(duì)象,從它可以獲取異步操作的消息從本意上講,它是承諾,承諾它過一段時(shí)間會(huì)給你一個(gè)結(jié)果。 如何寫一個(gè)符合promiseA+規(guī)范的promise實(shí)現(xiàn) 前言 Promise 是異步編程的一種解決方案:從語法上講,promise是一個(gè)對(duì)象,從它可以獲取異步操作的消息;從本意上講,它是承諾,承諾它過一段時(shí)間會(huì)給你一個(gè)結(jié)果。pr...

    hatlonely 評(píng)論0 收藏0
  • 步實(shí)現(xiàn)個(gè)符合PromiseA+規(guī)范Promise庫(kù)(1)

    摘要:今天我們來自己手寫一個(gè)符合規(guī)范的庫(kù)。是異步編程的一種解決方案,比傳統(tǒng)的解決方案回調(diào)函數(shù)和事件更合理和更強(qiáng)大。我們可以看到,其實(shí)就是一個(gè)構(gòu)造函數(shù)。所以說我們的數(shù)組里存的是一個(gè)一個(gè)的的回調(diào)函數(shù),也就是一個(gè)一個(gè)。 今天我們來自己手寫一個(gè)符合PromiseA+規(guī)范的Promise庫(kù)。大家是不是很激動(dòng)呢?? showImg(https://segmentfault.com/img/bV6t4Z?...

    joyvw 評(píng)論0 收藏0
  • Promise的源碼實(shí)現(xiàn)(完美符合Promise/A+規(guī)范

    摘要:以上代碼,可以完美通過所有用例。在的函數(shù)中,為何需要這個(gè)同樣是因?yàn)橐?guī)范中明確表示因此我們需要這樣的來確保只會(huì)執(zhí)行一次。其他情況,直接返回以該值為成功狀態(tài)的對(duì)象。 Promise是前端面試中的高頻問題,我作為面試官的時(shí)候,問Promise的概率超過90%,據(jù)我所知,大多數(shù)公司,都會(huì)問一些關(guān)于Promise的問題。如果你能根據(jù)PromiseA+的規(guī)范,寫出符合規(guī)范的源碼,那么我想,對(duì)于面試...

    gaomysion 評(píng)論0 收藏0
  • 性感的Promise,擁抱ta然后扒光ta

    摘要:,異步編程的流行解決方案,相比于古老的回調(diào)函數(shù)等方式,它更科學(xué),更優(yōu)雅。它來自民間,后被官方招安。實(shí)現(xiàn)方法,方法和狀態(tài)機(jī)制根據(jù)使用方法我們可以知道,是一個(gè)需要接受一個(gè)執(zhí)行器的構(gòu)造函數(shù),執(zhí)行器提供兩個(gè)方法,內(nèi)部有狀態(tài)機(jī)制,原型鏈上有方法。 Promise,js異步編程的流行解決方案,相比于古老的回調(diào)函數(shù)等方式,它更科學(xué),更優(yōu)雅。它來自民間,后被官方招安。 本文將從介紹用法開始,一步步了解...

    xushaojieaaa 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

econi

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<