談談Promise

首先看一段代碼


    setTimeout(function(){
        console.log(1)
    }, 3000)
    setTimeout(function(){
        console.log(2)
    }, 2000)
    setTimeout(function(){
        console.log(3)
    }, 1000)
        

此時會輸出 3 2 1, 原本我們是想輸出 1 2 3 的,但是在異步的情況下,我們沒辦法改變異步的順序,這是我們可以用回調(diào)函數(shù)來控制順序,但是又有一個扎心的問題 -- 回調(diào)地獄

這時我們的promise就出場啦,代碼改為:


    new Promise(function(resolve, reject){
        setTimeout(function(){
            console.log(1)
            resolve()
        }, 3000)
    })
    .then(function(data){
        return new Promise(function(resolve, reject){
            setTimeout(function(){
                console.log(2)
                resolve()
            }, 2000)
        })
    })
    .then(function(data){
        return new Promise(function(resolve, reject){
            setTimeout(function () {
                console.log(3)
                resolve()
            }, 1000)
        })
    })

在瀏覽器預覽: 隔3秒輸出1,再隔2秒輸出2,再隔1秒輸出3

這樣就符合我們預期的想法了

來看看代碼, 先new一下 證明我們第一步應該創(chuàng)建構造函數(shù) Promise(callback) ,接著后面有 then(fn) ,于是我們可以斷定 Promise.prototype.then = fn() {} , 于是根據(jù)執(zhí)行情況,我們可以把執(zhí)行順序捋一捋

Promise -> 接收的函數(shù)立即執(zhí)行 -> then(fn) (保存參數(shù)函數(shù)) -> resolve() -> then內(nèi)部的回調(diào)函數(shù)

我們再來看看,promomise里面有resolve和reject 那就可以看出promise有兩種狀態(tài),但這兩種只是判斷成功或者失敗,所以我們還需要一個初始狀態(tài)。 故: pending / fulfilled / rejected 這三種狀態(tài)

接著看代碼,看著注釋,就可以大致明白啦

var PENDING = 'PENDING';
var FULFILLED = 'FULFILLED';
var REJECTED = 'REJECTED';

// 1: 構造函數(shù)Promise
function Promise(fn) {
    // 2. 構造函數(shù)內(nèi)初始 狀態(tài)Pending 和 value
    this.status = PENDING; // 狀態(tài)是待發(fā)狀態(tài)
    this.value = null;  // 初始值
    this.deffered = []; // 下一個 要執(zhí)行的Promise是誰,子promise

    // 3.構造函數(shù)內(nèi)調(diào)用函數(shù)(apply參數(shù)是數(shù)組,call參數(shù)是一個個,調(diào)用函數(shù)改變this指向, bind不會立即調(diào)用,只是改變this)
    fn.call(this, this.resolve.bind(this), this.reject.bind(this));

}

// 4. 結束回調(diào)函數(shù), 執(zhí)行then Promise.prototype.then 是函數(shù)
// 5. then函數(shù)內(nèi)不需要保存起成果或者失敗的函數(shù)
Promise.prototype = {
    constructor: Promise, // 改變回來原型鏈
    then: function(onfulfilled, onrejected) {
        // 保存該函數(shù)
        var obj = {
            onfulfilled: onfulfilled,
            onrejected: onrejected
        }

        // 新來一個Promise對象,讓其存儲這些
        // 并且能根據(jù)不同的Promise去then
        obj.promise = new this.constructor(function(){});
        
        // 保存起接下來的promise
        // console.log(this)
        // console.log(obj.promise)

        // 建立上一個與下一個primise之間的關系
        if(this.status === PENDING) {
           this.deffered.push(obj); 
        }

        // 保證不報錯, 未來不能return自己  需要換人
        return obj.promise; // 下一個then的哥們

    },
    
    // 定義成功和失敗的回調(diào)函數(shù), 改變狀態(tài), 記錄數(shù)據(jù)結果, 執(zhí)行后續(xù)的行為
    resolve: function(data) {
        this.status = FULFILLED;
        this.value = data;
        // 執(zhí)行后續(xù)的行為
        this.done();
    },
    reject: function(err) {
        this.status = REJECTED;
        this.value = err;
        // 執(zhí)行后續(xù)的行為
        this.done();
    },
    // 執(zhí)行后續(xù)的行為
    done: function() {
        // 讓這些this.deffered(子promise得到執(zhí)行)
        this.deffered.forEach(task => this.handler(task));

    },
    handler: function(task) {   
        // 判斷當前執(zhí)行的狀態(tài)是怎樣, 調(diào)用對應的函數(shù)
        var status = this.status;
        var value = this.value;
        var p;
        switch(status) {
            case FULFILLED: 
                p = task.onfulfilled(value);
                break;
            case REJECTED:
                p = task.onrejected(value);
                break;
        }

        // 如果 p是一個promise的話,我們需要讓他們繼續(xù)執(zhí)行
        // 把后續(xù)(task.promise)的deffer 交給這個p
        if(p && p.constructor === Promise) {
            // 是一個promise
            // 把下一個作為then鏈接的deffer 移交給deffered
            p.deffered = task.promise.deffered;
        }
    },
}



我們按照思路先寫一個demo

var PENDING = 'PENDING'
var FULFILLED = 'FULFILLED'
var REJECTED = 'REJECTED'

// 1 構造函數(shù)Promise
function Promise(fn) {
    this.status = PENDING;  // 初始化狀態(tài)
    // 2 構造函數(shù)內(nèi)調(diào)用函數(shù) 
    this.value = null;  // 初始值
    this.deffered = [];  // 下一個執(zhí)行的Promise執(zhí)行是誰
    // 3 構造函數(shù)內(nèi)初始 狀態(tài)Pending 和 value
    fn()
}

// 4 結束回調(diào)函數(shù)后執(zhí)行then -> Promise.prototype.then 是函數(shù)
// 5 then函數(shù)內(nèi)部需要保存起成功或者失敗的函數(shù)
Promise.protope = {
    //  定義成功和失敗的回調(diào)函數(shù),改變狀態(tài),記錄數(shù)據(jù)結果, 執(zhí)行后續(xù)的行為
    resolve: function(data) {
        this.status = FULFILLED;
         this.value = dat
    },
    constructor: Promise,  // 改變回來原型鏈
    then: function() {

    }

}

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • Promise 對象 Promise 的含義 Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函...
    neromous閱讀 8,844評論 1 56
  • 官方中文版原文鏈接 感謝社區(qū)中各位的大力支持,譯者再次奉上一點點福利:阿里云產(chǎn)品券,享受所有官網(wǎng)優(yōu)惠,并抽取幸運大...
    HetfieldJoe閱讀 11,150評論 26 95
  • 本文適用的讀者 本文寫給有一定Promise使用經(jīng)驗的人,如果你還沒有使用過Promise,這篇文章可能不適合你,...
    HZ充電大喵閱讀 7,467評論 6 19
  • 這個很早以前寫的,今天看群里有人問關于promise的問題,在這里重新發(fā)一下。偷懶的同學可以直接拉到最后有完整的代...
    grain先森閱讀 3,031評論 1 9
  • 《從優(yōu)秀到卓越》是美國作者吉姆柯林斯《基業(yè)長青》之后的又一力作。它描繪了優(yōu)秀公司實現(xiàn)向卓越公司跨越的宏偉藍圖。在本...
    HiSwallow閱讀 945評論 0 0

友情鏈接更多精彩內(nèi)容