欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript自定義Promise實現(xiàn)流程

 更新時間:2022年10月22日 11:08:15   作者:YinJie…  
現(xiàn)在網(wǎng)上有非常多的Promise文章,但都是給你一堆代碼,或者某些核心代碼,讓你看完之后感覺,嗯,很厲害,但還是不知所云,不知其所以然。那么本文真正從一個小白開始帶你深入淺出,一步一步實現(xiàn)自己的?Promise,這種自己造輪子的過程一定是進(jìn)步最快的過程,快上車開始吧

1. 初始結(jié)構(gòu)

我們先來回顧下 js 里 promise 實例是如何創(chuàng)建的:

let promsie = new Promise((resolve, reject) => {
    resolve('完成了')
})

那這樣我們就知道了,在我們創(chuàng)建的 promise 類中的構(gòu)造函數(shù)要傳入的是一個函數(shù),而且我們在傳入?yún)?shù)的時候,這個函數(shù)參數(shù)會被自動執(zhí)行,接下來這個函數(shù)參數(shù)也有自己的參數(shù),也就是 resolve 和 reject 這兩個參數(shù),那我們也得讓我們手寫的 myPromise 支持這兩個參數(shù):

class myPromise {
    constructor(func) {
        func(resolve,reject)
    }
}

這么寫顯然是有問題的,因為我們不知道在哪里調(diào)用 resolve 和 reject 這兩個參數(shù),因為我們還沒有定義這兩個對象,這兩個對象還是函數(shù),因此下面就要用類方法的形式創(chuàng)建這兩個函數(shù):

class myPromise {
    constructor(func) {
        func(resolve,reject)
    }
    resolve() {}
    reject() {}
}

這樣是對的了么?

錯啦,因為我們得用 this 才能調(diào)用自身的方法,所以要在兩個參數(shù)前加上 this:

class myPromise {
    constructor(func) {
        func(this.resolve,this.reject)
    }
    resolve() {}
    reject() {}
}

2. 定義狀態(tài)

promise 里有三種狀態(tài),分別是 pending,fulfilled 和 rejected,要注意狀態(tài)一經(jīng)改變就不能再改變了且只能由 pending 轉(zhuǎn)化為 fulfilled 或者 pending 轉(zhuǎn)化為 rejected。所以我們可以提前把這些狀態(tài)定義好,可以用 const 來創(chuàng)建外部的固定變量,然后將 pending 設(shè)置為默認(rèn)狀態(tài),這樣在每一個實例被創(chuàng)建以后就會有自身的狀態(tài)屬性可以進(jìn)行判斷和變動了:

class myPromise {
    static PENDING = '待定'
    static FULFILLED = '成功'
    static REJECTED = '拒絕'
    constructor(func) {
        this.status = myPromise.PENDING
        func(this.resolve,this.reject)
    }
    resolve() {
        if (this.status === myPromise.PENDING) {
            this.status = myPromise.FULFILLED
        }
    }
    reject() {
        if (this.status === myPromise.PENDING) {
            this.status = myPromise.REJECTED
        }
    }
}

當(dāng)執(zhí)行 reolve 的時候,如果現(xiàn)在的狀態(tài)是待定,就讓他變?yōu)槌晒Γ?reject 同理。

并且,在執(zhí)行 resolve 或者 reject 的時候都是可以傳入一個參數(shù)的,這樣后面就能使用這個參數(shù)了:

class myPromise {
    static PENDING = '待定'
    static FULFILLED = '成功'
    static REJECTED = '拒絕'
    constructor(func) {
        this.status = myPromise.PENDING
        this.result = null
        func(this.resolve,this.reject)
    }
    resolve(result) {
        if (this.status === myPromise.PENDING) {
            this.status = myPromise.FULFILLED
            this.result = result
        }
    }
    reject(result) {
        if (this.status === myPromise.PENDING) {
            this.status = myPromise.REJECTED
            this.result = result
        }
    }
}

那現(xiàn)在我們 new 一個 myPromise 的實例,大家覺得會不會成功呢?

3. this指向

承接上文,我們 new 了一個實例對象:

let promise = new myPromise((resolve,reject) => {
    resolve('小杰學(xué)前端')
})

下面是輸出結(jié)果:

控制臺不出意外的報錯了,其實問題就出在這里:

我們在 resolve 中拿不到 status ,也就是 this 已經(jīng)跟丟了,這是為什么呢?

因為我們在 new 一個新實例的時候,執(zhí)行的是 constructor 里的內(nèi)容,也就是 constructoe 里的 this 指向的是實例對象,但是現(xiàn)在我們是在實例對象被創(chuàng)建后再在外部環(huán)境下執(zhí)行 resolve 方法的,這里的 resolve 看著像是和實例一起執(zhí)行的,其實不然。解決 class 的 this 指向問題一般會用箭頭函數(shù), bind 或者 proxy,這里我們就用 bind 來綁定

class myPromise {
    static PENDING = '待定'
    static FULFILLED = '成功'
    static REJECTED = '拒絕'
    constructor(func) {
        this.status = myPromise.PENDING
        this.result = null
        func(this.resolve.bind(this),this.reject.bind(this))
    }
    resolve(result) {
        if (this.status === myPromise.PENDING) {
            this.status = myPromise.FULFILLED
            this.result = result
        }
    }
    reject(result) {
        if (this.status === myPromise.PENDING) {
            this.status = myPromise.REJECTED
            this.result = result
        }
    }
}

這里就是給實例的 resolve 和 reject 方法綁定這個 this 為當(dāng)前的實例對象

或者我們也可以這樣解決:

class myPromise {
    static PENDING = '待定'
    static FULFILLED = '成功'
    static REJECTED = '拒絕'
    constructor(func) {
        this.status = myPromise.PENDING
        this.result = null
        let resolve = (result) => {
            if (this.status === myPromise.PENDING) {
                this.status = myPromise.FULFILLED
                this.result = result
            }
        }
        let reject = (result) => {
            if (this.status === myPromise.PENDING) {
                this.status = myPromise.REJECTED
                this.result = result
            }
        }
        func(resolve, reject)
    }
}

4. then 方法

我們先回顧一下原生的 then 是怎么寫的:

let promise = new Promise((resolve, reject) => {
    resolve('完成了')
    reject('失敗了')
})
promise.then(
    res => console.log(res),
    result => console.log(result))

那我們就開始寫我們的 then ,首先知道的是要傳遞兩個參數(shù),他們都是函數(shù)類型,一個表示狀態(tài)成功時的回調(diào),一個表示狀態(tài)失敗時的回調(diào):

class myPromise {
    static PENDING = '待定'
    static FULFILLED = '成功'
    static REJECTED = '拒絕'
    constructor(func) {
        this.status = myPromise.PENDING
        this.result = null
        func(this.resolve.bind(this),this.reject.bind(this))
    }
    resolve(result) {
        if (this.status === myPromise.PENDING) {
            this.status = myPromise.FULFILLED
            this.result = result
        }
    }
    reject(result) {
        if (this.status === myPromise.PENDING) {
            this.status = myPromise.REJECTED
            this.result = result
        }
    }
    then(onFulfilled, onRejected) {
        if (this.status === myPromise.FULFILLED) {
            onFulfilled(this.result)
        }
        if (this.status === myPromise.REJECTED) {
            onRejected(this.result)
        }
    }
}

這里 then 寫的也是淺顯易懂,我們測試一下能否正常輸出:

let promise = new myPromise((resolve,reject) => {
    resolve('成功了')
    reject('失敗了')
}
promise.then(res => console.log(res),
        result => console.log(result)) // 成功了

5. 執(zhí)行異常

如果我們在 new Promise 的時候,執(zhí)行函數(shù)里面我們拋出錯誤,是會觸發(fā)拒絕方法,可以把錯誤的信息作為內(nèi)容輸出出來:

let promise = new Promise((resolve, reject) => {
    throw new Error('拋出錯誤')
})
promise.then(
    res => console.log(res),
    result => console.log(result)) //Error: 拋出錯誤

但是如果我們在 myPromise 這里寫上同樣的代碼則會報錯,于是我們就可以在執(zhí)行 resolve 和 reject 之前進(jìn)行判斷,可以用 try 和 catch 來該寫代碼,如果沒有報錯就正常執(zhí)行,有報錯就調(diào)用 reject 方法:

constructor(func) {
        this.status = myPromise.PENDING
        this.result = null
        try {
            func(this.resolve.bind(this),this.reject.bind(this))
        } catch (error) {
            this.reject(error)
        }
    }

注意,在 catch 這里不需要用 bind ,因為這是立即調(diào)用的,只在內(nèi)部執(zhí)行的。

那到了這里我們的異常處理是不是和原生的差不多了呢,其實還沒有,我們知道在 then 里傳遞的是兩個函數(shù)參數(shù),那如果我們故意在原生代碼里不傳入函數(shù)作為參數(shù)呢:

let promise = new Promise((resolve, reject) => {
    resolve('成功了')
})
promise.then(
    undefined,
    result => console.log(result)) 

實際上,這里什么也沒有輸出,但是如果我們以同樣的方法應(yīng)用在 myPromise 里會發(fā)生什么呢?

答案是會報一堆錯誤,這不是我們想要的,那我們只需要在執(zhí)行 then 里的參數(shù)前進(jìn)行類型判斷,如果它是函數(shù)就把原函數(shù)參數(shù)賦給它,否則就賦給它空函數(shù):

then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {}
        onRejected = typeof onRejected === 'function' ? onRejected : () => {}
        if (this.status === myPromise.FULFILLED) {
            onFulfilled(this.result)
        }
        if (this.status === myPromise.REJECTED) {
            onRejected(this.result)
        }
    }

現(xiàn)在再運(yùn)行就不會報錯了。

6. 支持異步(重頭戲1)

現(xiàn)在我們的手寫代碼里面還沒有植入異步功能,首先我們先了解一下原生 Promise 的一些運(yùn)行順序規(guī)則:

console.log(111)
let promise = new Promise((resolve, reject) => {
    console.log(222)
    resolve('成功了')
})
console.log(333)
promise.then(
    res => console.log(res),
    result => console.log(result)) 

熟悉 JS 執(zhí)行機(jī)制和 prmoise 的同學(xué)一定能夠正確的判斷輸出的順序:

我們再看一下手寫的 myPromise 是如何輸出的:

console.log(111)
let promise = new myPromise((resolve,reject) => {
    console.log(222)
    resolve('成功了')
})
promise.then(res => console.log(res),
        result => console.log(result)) // 成功了
console.log(333)

執(zhí)行代碼,查看輸出:

那我們已經(jīng)找到問題的所在了,那就是 resolve 和 reject 里面都沒有設(shè)置異步執(zhí)行,二話不說直接套上定時器:

then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {}
        onRejected = typeof onRejected === 'function' ? onRejected : () => {}
        if (this.status === myPromise.FULFILLED) {
            setTimeout(() => {
                onFulfilled(this.result)
            }, 0);
        }
        if (this.status === myPromise.REJECTED) {
            setTimeout(() => {
                onRejected(this.result)
            }, 0);
        }
    }

現(xiàn)在我們的 then 里面就是異步執(zhí)行的了,再次運(yùn)行代碼查看輸出:

可以看到我們成功輸出了,但是現(xiàn)在異步的問題真的解決了嗎,現(xiàn)在又進(jìn)入另一個非常!非常!重要的重點了,我們先看一下原生 Promise 這段代碼:

console.log(111)
let promise = new Promise((resolve, reject) => {
    console.log(222)
    setTimeout(() => {
        resolve('成功了')
        console.log(444)
    }, 0);
})
console.log(333)
promise.then(
    res => console.log(res),
    result => console.log(result))

這段代碼的輸出如下:

在 setTimeout 中會先執(zhí)行輸出444,再執(zhí)行 resolve ,我們再看一下同樣的代碼放在 myPromise 中的輸出結(jié)果:

并沒有輸出 “ 成功了 ”,這是為什么呢?

沒有輸出很可能的原因是 then 方法沒有被執(zhí)行,我們再各個位置輸出一下當(dāng)前的狀態(tài),進(jìn)行判斷:

console.log(111)
let promise = new myPromise((resolve,reject) => {
    console.log(222)
    setTimeout(() => {
        console.log(myPromise.status)
        resolve('成功了')
        console.log(myPromise.status)
        console.log(444)
    }, 0);
})
promise.then(res => { console.log(res); console.log(myPromise.status) },
        result => console.log(result)) // 成功了
console.log(333)

看一下控制臺輸出:

可以看到在 setTimeout 里面的兩個狀態(tài)都被成功輸出了只有then 里的狀態(tài)并沒有成功輸出出來,那基本就可以判斷是 then 里的判斷出了問題,我們先分析一下,在執(zhí)行完 111,222,333后就開始處理異步,這里肯定是因為我們先執(zhí)行了 then ,然后在 then 里會判斷當(dāng)前狀態(tài)是成功就執(zhí)行成功的回調(diào),是失敗就執(zhí)行失敗的回調(diào),但是如果當(dāng)前狀態(tài)是 pending 呢?這不就出問題了嗎,在本題中 setTimeout 是宏任務(wù),要晚于微任務(wù) then 執(zhí)行,所以 then 執(zhí)行的時候還沒有改變狀態(tài),自然就不會輸出,那我們就在 then 里添加待定狀態(tài)的條件就可以了。

7. 回調(diào)保存(重頭戲2)

因為在函數(shù)體中執(zhí)行異步操作時,then 會先執(zhí)行,所以我們要在 then 里狀態(tài)為 pending ,也就是碰到異步操作的時候讓 then 里的函數(shù)稍后再執(zhí)行,等到狀態(tài)改變了再去執(zhí)行,那我們就定義兩個數(shù)組來保存回調(diào)

constructor(func) {
        this.status = myPromise.PENDING
        this.result = null
        this.resolveCallbacks = []
        this.rejectCallbacks = []
        try {
            func(this.resolve.bind(this),this.reject.bind(this))
        } catch (error) {
            this.reject(error)
        }
    }

然后在 then 里狀態(tài)為 pending 時將函數(shù)保存:

then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {}
        onRejected = typeof onRejected === 'function' ? onRejected : () => {}
        if (this.status === myPromise.PENDING) {
             this.resolveCallbacks.push(() => {
                    onFulfilled(this.result)
             })
             this.rejectCallbacks.push(() => {
                    onRejected(this.result)
             })
        }
        if (this.status === myPromise.FULFILLED) {
            setTimeout(() => {
                onFulfilled(this.result)
            }, 0);
        }
        if (this.status === myPromise.REJECTED) {
            setTimeout(() => {
                onRejected(this.result)
            }, 0);
        }
    }

然后在執(zhí)行 resolve 和 reject 的時候,看看回調(diào)數(shù)組里有沒有待執(zhí)行的函數(shù),有的話就執(zhí)行:

resolve(result) {
        if (this.status === myPromise.PENDING) {
            this.status = myPromise.FULFILLED
            this.result = result
            this.resolveCallbacks.forEach(callback => {
                callback(result)
            })
        }
    }
    reject(result) {
        if (this.status === myPromise.PENDING) {
            this.status = myPromise.REJECTED
            this.result = result
            this.rejectCallbacks.forEach(callback => {
                callback(result)
            })
        }
    }

現(xiàn)在我們再運(yùn)行一下原來的測試代碼:

console.log(111)
let promise = new myPromise((resolve,reject) => {
    console.log(222)
    setTimeout(() => {
        resolve('成功了')
        console.log(444)
    }, 0);
})
promise.then(res => { console.log(res) },
        result => console.log(result)) 
console.log(333)

現(xiàn)在輸出的是:

這個輸出結(jié)果也不是我們預(yù)期的呀,我們雖然成功輸出了執(zhí)行成功的回調(diào),但是應(yīng)該是在444后面輸出才對,其實這里還有個小坑,就是 resolve 和 reject 也得讓他倆變成異步執(zhí)行:

resolve(result) {
        setTimeout(() => {
            if (this.status === myPromise.PENDING) {
                this.status = myPromise.FULFILLED
                this.result = result
                this.resolveCallbacks.forEach(callback => {
                    callback(result)
                })
            }
        }, 0);
    }
    reject(result) {
        setTimeout(() => {
            if (this.status === myPromise.PENDING) {
                this.status = myPromise.REJECTED
                this.result = result
                this.rejectCallbacks.forEach(callback => {
                    callback(result)
                })
            }
        }, 0);
    }

執(zhí)行結(jié)果:

因為我們知道在 promise 的函數(shù)體內(nèi)是同步執(zhí)行的,promise.then 是微任務(wù),會異步執(zhí)行,所以在函數(shù)體內(nèi)碰到 resolve 時雖然狀態(tài)改變了但是并不會立刻輸出 result ,但是因為現(xiàn)在我們的函數(shù)體內(nèi)有異步代碼,此時我們執(zhí)行 then 只是把他的回調(diào)保存起來了,等到執(zhí)行回調(diào)的時候還得恢復(fù)原來的邏輯,也就是等函數(shù)體內(nèi)同步代碼輸出完了再執(zhí)行 then 輸出 resolve 里傳遞的值,所以要給 resolve 和 reject 加 setTimeout 讓他變成異步,不這樣的話在執(zhí)行 resolve 狀態(tài)改變了就會立刻輸出結(jié)果,這顯然不是我們期待的。

8. 重難點解讀

如果你之前還是云里霧里沒有懂的話,我們再次來解讀一下這段代碼:

console.log(111)
let promise = new myPromise((resolve,reject) => {
    console.log(222)
    setTimeout(() => {
        resolve('成功了')
        console.log(444)
    }, 0);
})
promise.then(res => { console.log(res) },
        result => console.log(result)) 
console.log(333)
  • 第一步,執(zhí)行 console.log(111),輸出 ”111“
  • 第二步,創(chuàng)建 promise,同步執(zhí)行函數(shù)體內(nèi)的代碼,執(zhí)行 console.log(222),輸出 “222”
  • 第三步,遇到 setTimeout,這是宏任務(wù),將他放到宏任務(wù)隊列,等待執(zhí)行
  • 第四步,遇到 promise.then ,這是微任務(wù),將它放到微任務(wù)隊列,等待執(zhí)行
  • 第五步,執(zhí)行 console.log(333) ,輸出 “333”
  • 第六步,當(dāng)前執(zhí)行棧已經(jīng)清空,先執(zhí)行微任務(wù)隊列的任務(wù) promise.then ,發(fā)現(xiàn)當(dāng)前狀態(tài)還是待定,所以沒有輸出,沒有輸出的原因是改變狀態(tài)的 resolve 函數(shù)在 setTimeout 里,而我們目前還沒有執(zhí)行,然后將 then 的回調(diào)保存起來。
  • 第七步,微任務(wù)隊列已經(jīng)清空,開始執(zhí)行宏任務(wù) setTimeout,因為 resolve 也是異步執(zhí)行的,所以放到異步隊列中,先執(zhí)行同步任務(wù) console.log(444),輸出 “444”
  • 第八步,現(xiàn)在沒有要執(zhí)行的同步任務(wù)了,再執(zhí)行 resolve ,改變當(dāng)前狀態(tài)為成功,然后發(fā)現(xiàn)回調(diào)數(shù)組里有待執(zhí)行的函數(shù),執(zhí)行回調(diào)函數(shù),輸出結(jié)果 “成功了”

9. 鏈?zhǔn)焦δ埽ㄖ仡^戲3)

我們先了解一下 then 方法的特點,then方法中的成功回調(diào)或者失敗回調(diào),如果返回的是一個promise ,那么這個 promise 成功或者失敗的值就會傳遞給下一個 then 中。如果返回的是一個普通的不是 promise 的值,那就把這個值傳給下一個 then 。如果執(zhí)行時出現(xiàn)錯誤那就會執(zhí)行下一個 then 中的失敗的回調(diào)。

注意是參數(shù)函數(shù)的返回值,而不是then本身的返回值,then本身肯定是返回promise的。

那么首先我們現(xiàn)在要做的就是拿到上一個回調(diào)中返回的值:

then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {}
        onRejected = typeof onRejected === 'function' ? onRejected : () => {}
        let newPromise = new myPromise((resolve, reject) => {
            if (this.status === myPromise.PENDING) {
                this.resolveCallbacks.push(() => {
                    let res = onFulfilled()
                })
                this.rejectCallbacks.push(() => {
                    let res = onRejected()
                })
            }
            if (this.status === myPromise.FULFILLED) {
                setTimeout(() => {
                    let res = onFulfilled(this.result)
                }, 0);
            }
            if (this.status === myPromise.REJECTED) {
                setTimeout(() => {
                    let res = onRejected(this.result)
                }, 0);
            }
        })
        return newPromise
    }

then能執(zhí)行的前提是,對應(yīng)的promise執(zhí)行了resolve,這樣能拿到resolve的值。

所以后面的then能拿到的前提是:前面的then(返回值是promise) 將參數(shù)函數(shù)返回值resolve了。這里面略繞,得好好想想。所以我們現(xiàn)在需要執(zhí)行 resolve 并且把上一個回調(diào)傳進(jìn)來的值作為參數(shù):

then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {}
        onRejected = typeof onRejected === 'function' ? onRejected : () => {}
        let newPromise = new myPromise((resolve, reject) => {
            if (this.status === myPromise.PENDING) {
                this.resolveCallbacks.push(() => {
                    let res = onFulfilled(this.result)
                    resolve(res)
                })
                this.rejectCallbacks.push(() => {
                    let res = onRejected(this.result)
                    resolve(res)
                })
            }
            if (this.status === myPromise.FULFILLED) {
                setTimeout(() => {
                    let res = onFulfilled(this.result)
                    resolve(res)
                }, 0);
            }
            if (this.status === myPromise.REJECTED) {
                setTimeout(() => {
                    let res = onRejected(this.result)
                    resolve(res)
                }, 0);
            }
        })
        return newPromise
    }

現(xiàn)在我們的工作完成了么?還沒有,準(zhǔn)確的說核心邏輯完成了一半,我們還沒有處理返回值是 promise 對象的情況,下面我們直接把這塊的邏輯抽象成一個函數(shù):

then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {}
        onRejected = typeof onRejected === 'function' ? onRejected : () => {}
        let newPromise = new myPromise((resolve, reject) => {
            if (this.status === myPromise.PENDING) {
                this.resolveCallbacks.push(() => {
                    let res = onFulfilled(this.result)
                    this.resolvePromise(res,resolve,reject)
                })
                this.rejectCallbacks.push(() => {
                    let res = onRejected(this.result)
                    this.resolvePromise(res,resolve,reject)
                })
            }
            if (this.status === myPromise.FULFILLED) {
                setTimeout(() => {
                    let res = onFulfilled(this.result)
                    this.resolvePromise(res,resolve,reject)
                }, 0);
            }
            if (this.status === myPromise.REJECTED) {
                setTimeout(() => {
                    let res = onRejected(this.result)
                    this.resolvePromise(res,resolve,reject)
                }, 0);
            }
        })
        return newPromise
    }
    resolvePromise(res, resolve, reject) {
        if(res instanceof myPromise) {
            res.then(resolve, reject)
          } else{
            // 普通值
            resolve(res)
          }
    }

那么現(xiàn)在我們通過實例看一下能否實現(xiàn)鏈?zhǔn)秸{(diào)用,當(dāng)返回值是 promise 的時候:

let promise = new myPromise((resolve,reject) => {
    resolve(11)
})
const a = new Promise((resolve,reject) => {
    resolve('ok')
})
promise.then(res => { return a }).then(res => console.log(res))

運(yùn)行結(jié)果:

當(dāng)返回值是普通值的時候:

let promise = new myPromise((resolve,reject) => {
    resolve(11)
})
promise.then(res => { return res }).then(res => console.log(res)) //11

可以看到現(xiàn)在我們的鏈?zhǔn)秸{(diào)用已經(jīng)基本實現(xiàn)了功能,其實這里面還有很多邊界情況沒有做處理,還實現(xiàn)的很粗糙,但是我們研究源碼要做的就是抽絲剝繭,關(guān)注最核心的邏輯就行,當(dāng)然能把邊界情況都處理了是最好的。

到此這篇關(guān)于JavaScript自定義Promise實現(xiàn)流程的文章就介紹到這了,更多相關(guān)JavaScript Promise內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論