Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promise A+实现 #21

Open
zhangyanan0525 opened this issue Sep 16, 2018 · 1 comment
Open

Promise A+实现 #21

zhangyanan0525 opened this issue Sep 16, 2018 · 1 comment

Comments

@zhangyanan0525
Copy link
Owner

zhangyanan0525 commented Sep 16, 2018

Promise A+实现

资料来自美团技术博客剖析 Promise 之基础篇

1.最简单的用法

实际应用方式

function foo() {
    return new MyPromise(function (resolve) {
        setTimeout(()=>{
            resolve('2')
        },3000)
    })
}

foo().then(function (id) {
    console.log(id)
})

分析

1.foo函数执行过后返回一个MyPromise实例
2.MyPromise传入一函数,此函数的参数为resolve。我们执行了这个函数。并且通过将我们异步操作的结果传入了resolve
3.foo函数返回的MyPromise实例,有一个then方法。这个方法的参数是一个函数。这个函数承接了foo函数里异步操作的结果

代码实现

function MyPromise(fn) {  
    var callbacks = [];                          

    this.then = function (onFulfilled) {   
        callbacks.push(onFulfilled)              
    };                                    

    function resolve(value) {  
        callbacks.forEach(function(callback){       
            callback(value);                         
        })      
    }                        

    fn(resolve);  
}

2.延时

实际应用方式

function foo() {
    return new MyPromise(function (resolve) {
        resolve('2')
    })
}

foo().then(function (id) {
    console.log(id)
})

分析

1.如果 promise 是同步代码,resolve 会先于 then 执行,这时 callbacks 队列还空无一物
2.此外,Promises/A+ 规范明确要求回调需要通过异步方式执行,用以保证一致可靠的执行顺序

代码实现

function MyPromise(fn) {                      
    var callbacks = [] ;                        

    this.then = function (onFulfilled) {          
        callbacks.push(onFulfilled) 
    };                                            

    function resolve(value) {    
        setTimeout(function() {                 
            callbacks.forEach(function(callback){       
                callback(value);                        
            })
        },0)
    }                                              

    fn(resolve);                                   
}

3.引入状态

实际应用方式

function foo() {
    return new MyPromise(function (resolve) {
        resolve('2')
    })
}

let a = foo()
// 过了不知道多久调用
a.then(function (id) {
    console.log(id)
})

分析

1.如果foo已经执行了,在异步操作成功之前注册的回调都会执行,但是在这之后调用的then注册的回调就再也不会执行了
2.我们想实现的逻辑是,在异步之前注册的回调,等待异步完成后执行。异步完成后注册的回调,立即执行
3.所以我们必须加一个状态机。判断异步是否完成

代码实现

function MyPromise(fn) {                        
    var callbacks = [] ;  
    var state = 'pending';
    var value = null                   

    this.then = function (onFulfilled) {   
        if(state === 'pending'){
            callbacks.push(onFulfilled) 
        }
        onFulfilled(value)
        return this;                          
    };                                            

    function resolve(newValue) {   
        value =  newValue
        state = 'fulfilled';
        setTimeout(function() {                 
            callbacks.forEach(function(callback){       
                callback(value);                         
            })
        },0)
    }                                               

    fn(resolve);                                  
}

4.串行 Promise

实际应用方式

function foo() {
    return new MyPromise(function (resolve) {
        setTimeout(() => {
            return resolve('2')
        }, 3000);
    })
}
foo().then(function (id) {
    return new MyPromise(function(resolve){
        setTimeout(() => {
            return resolve(id+'张三')
        }, 3000);
    })
}).then(function (res) {
    return '张三'
}).then(function (name) {
    console.log(name)
})

分析

// 将以上代码抽象为:
P1.then(function(id){
    return P2
}).then(function (name) {
    console.log(name)
})

// 还可以进一步抽象为
let P0 = P1.then(function(id){
    return P2
})

let p3 = P0.then(function (name) {
    console.log(name)
})

1.p2的resolve能执行谁,p0的then中的注册函数又是谁执行的?
2.p2的resolve能执行谁p2的then中的注册函数,p0的then中的注册函数是P0的resolve执行掉的
3.那我们只要把p0的resolve传给p2的then中的注册函数。那就能让p2执行p0的then

代码实现

function MyPromise(fn) {                         
    var callbacks = [] ;  
    var value = null  
    var state = 'pending'

    this.then = function (onFulfilled) {   
        return new MyPromise(function (resolve) {
            if (state === 'pending') {
                callbacks.push({onFulfilled,resolve});
            }
        });                       
    };                                            
    function resolve(newValue) {   
        if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
            var then = newValue.then;
            if (typeof then === 'function') {
                // P2.then(resolve)
                then.call(newValue, resolve);
                return;
            }
        }
        state = 'fulfilled'
        value = newValue;
        setTimeout(function () {
            callbacks.forEach(function ({onFulfilled,resolve}) {
                var ret = onFulfilled(value);
                resolve(ret);
            });
        }, 0);
    }                                               

    fn(resolve);                                   
}

代码解释

1.p1对应的MyPromise state是'pending',callbacks是[] --》 callbacks塞了{onFulfilled,p0的resolve} --》 state是'fulfilled',value是2
2.p0对应的MyPromise state是'pending',callbacks是[] --》 callbacks塞了{onFulfilled,p3的resolve}
3.p3对应的MyPromise state是'pending',callbacks是[]

@xiejinhe
Copy link

厉害了小姐姐

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants