溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

js中promise對(duì)象有什么用

發(fā)布時(shí)間:2020-12-07 14:05:59 來(lái)源:億速云 閱讀:148 作者:小新 欄目:web開(kāi)發(fā)

這篇文章主要介紹了js中promise對(duì)象有什么用,具有一定借鑒價(jià)值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。

js中的異步,剛開(kāi)始的時(shí)候都是用回調(diào)函數(shù)實(shí)現(xiàn)的,所以如果異步嵌套的話(huà),就有出現(xiàn)回調(diào)地獄,使得代碼難以閱讀和難以維護(hù),后來(lái)es6出現(xiàn)了promise,解決了回調(diào)地獄的問(wèn)題?,F(xiàn)在我們就自己寫(xiě)代碼實(shí)現(xiàn)一下promise,這樣才能深入理解promise的運(yùn)行機(jī)制,對(duì)以后使用promise也能夠更加得心應(yīng)手。開(kāi)始之前可以先看下promise的官網(wǎng)promise/A+

先來(lái)看下promise的用法

new Promise((resolve,reject)=>{
  resolve(1);
  reject(11);
}).then(res=>{
  console.log(res);
  setTimeout(()=>{
    return new Promise((resolve,reject)=>{
        resolve(2)
    }) 
  },1000)
}).then(res2=>{
  console.log(res2);
});

控制臺(tái)打印
1
...1s later
2

先分析下上面這段代碼,先提出幾個(gè)問(wèn)題
1.第一段resolve和reject都有,但是只輸出了1,為什么?
2.then里的res是如何取到resolve中的值的?
3.promise是如何做到鏈?zhǔn)秸{(diào)用的?

狀態(tài)機(jī)

promise中有個(gè)狀態(tài)機(jī)的概念,先說(shuō)下為什么要有狀態(tài)機(jī)的概念呢,因?yàn)閜romise的狀態(tài)是單向變化的,有三種狀態(tài),pending,fullfilled,rejected,而這三種狀態(tài)只能從pending->fullfilled或者pending->rejected這兩種形式,也就是說(shuō)執(zhí)行了fullfilled之后,就不會(huì)執(zhí)行rejected。這就解釋了上面的第一個(gè)問(wèn)題。

下面我們來(lái)看下具體實(shí)現(xiàn)的完整代碼

const PENDING = 'PENDING';
const FULLFILLED = 'FULLFILLED';
const REJECTED = 'REJECTED';    
class Promise{
    constructor(fn){
       this.status = PENDING;//狀態(tài)
        this.data = undefined;//返回值
        this.defercb = [];//回調(diào)函數(shù)數(shù)組
        //執(zhí)行promise的參數(shù)函數(shù),并把resolve和reject的this綁定到promise的this
        fn(this.resolve.bind(this),this.reject.bind(this));
    }
    resolve(value){
        if(this.status === PENDING){
            //只能pending=>fullfied
            this.status = FULLFILLED;
            this.data = value;
            this.defercb.map(item=>item.onFullFilled());
        }
    }
    reject(value){
        if(this.status === PENDING){
            //只能pending=>rejected
            this.status = REJECTED;
            this.data = value;
            this.defercb.map(item=>item.onRejected());
        }
    }
    then(resolveThen,rejectThen){
       //如果沒(méi)有resolveThen方法,保證值可以穿透到下一個(gè)then里有resolveThen的方法中
        resolveThen = typeof resolveThen === 'function' ? resolveThen : function(v) {return v};
        rejectThen = typeof rejectThen === 'function' ? rejectThen : function(r) {return r};
        //返回的都是promise對(duì)象,這樣就可以保證鏈?zhǔn)秸{(diào)用了
        switch(this.status){
            case PENDING:
            return new Promise((resolve,reject)=>{
                const onFullFilled = () => {
                    const result = resolveThen(this.data);//這里調(diào)用外部then的resolveThen方法,將值傳回去
                    //如果返回值是promise對(duì)象,執(zhí)行then方法,取它的結(jié)果作為新的promise實(shí)例的結(jié)果,因?yàn)閠his.data會(huì)重新賦值
                    result instanceof Promise && result.then(resolve,reject);
                }
                const onRejected = ()=>{
                    const result = rejectThen(this.data);
                    result instanceof Promise && result.then(resolve,reject);
                }
                this.defercb.push({onFullFilled,onRejected});
            });
            break;
            case FULLFILLED:
               return new Promise((resolve,reject)=>{
                     const result = resolveThen(this.data);
                     result instanceof Promise && result.then(resolve,reject);
                     resolve(result);
               })
            break;
            case REJECTED:
               return new Promise((resolve,reject)=>{
                   const result = rejectThen(this.data);
                   result instanceof Promise && result.then(resolve,reject);
                   reject(result)
               })   
            break;
        }
    }
}

運(yùn)行下面的例子

new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(1);
    }, 1000);
}).then((res2) => {
    console.log(res2);
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2);
        }, 1000);
    });
}).then((res3) => {
    console.log(res3);
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(3);
        }, 1000);
    });
}).then((res4) => {
    console.log(res4);
});

控制臺(tái)打印
...1s later
1
...1s later
2
...1s later
3
說(shuō)明上面的實(shí)現(xiàn)是沒(méi)有問(wèn)題的
不過(guò)還有一個(gè)問(wèn)題,就是事件循環(huán)的順序問(wèn)題,比如執(zhí)行下面的代碼

new Promise((resolve) => {
    resolve();
})
.then(() => {
    console.log('1');
})
.then(() => {
    console.log('2');
});
console.log('3');

并沒(méi)有像預(yù)想中輸出3,1,2,而是輸出了1,2,3,原因就是因?yàn)槲覀兊倪@個(gè)Promise是在主線程中,沒(méi)有在下一個(gè)任務(wù)隊(duì)列中,可以加上settimeout解決這個(gè)問(wèn)題,不過(guò)這也只是為了讓我們更好理解執(zhí)行順序而已,然而實(shí)際上是promise是屬于微任務(wù)中的,而settimeout是屬于宏任務(wù),還是不太一樣的

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享js中promise對(duì)象有什么用內(nèi)容對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,遇到問(wèn)題就找億速云,詳細(xì)的解決方法等著你來(lái)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI