美文网首页
promise.then

promise.then

作者: 看到这朵小fa了么 | 来源:发表于2020-03-12 14:37 被阅读0次

https://cloud.tencent.com/developer/article/1361997

promise的then做了什么

学习: https://segmentfault.com/a/1190000010420744?utm_source=tag-newest

  • then接受两个参数 promise.then(onFullfilled, onRejected),会返回一个promise对象,这也是链式调用的原理
  • 对传入的两个回调函数进行处理
    1、如果为值 则直接resolve该值
    2、如果为普通函数,则执行该函数,函数的返回值作为普通值则resolve该值,没有返回值则resolve上次的值(透传)
    3、如果返回值为promise函数,则执行该函数,并取当前返回的promise函数作为resolve值进行透传(也就是这次的状态跟返回的promise对象状态保持一致)
  • 根据当前状态不同处理回调
    1、pending态,返回promise,并将两个回调函数分别压栈
    2、fullfilled或rejected态,返回promise,并执行对应的(onFullfilled(thia.value), onRejected(this.reason))函数
let func = function() {
    return new Promise((resolve, reject) => {
        resolve('返回值');
    });
};

let cb = function() {
    return '新的值';
}
// 是函数 则将函数的返回值cb() 执行了 的值返回给下一个then
func().then(function () {
    return cb();
}).then(resp => {
    console.warn(resp); // 新的值
    console.warn('1 =========<');
});
// 执行了 但是没有返回值
func().then(function () {
    cb();
}).then(resp => {
    console.warn(resp); // undefined
    console.warn('2 =========<');
});
// 是一个值 被忽略 返回了上一个then resolve的值
func().then(cb()).then(resp => {
    console.warn(resp); // 返回值
    console.warn('3 =========<');
});
// 是一个函数且有返回值 
func().then(cb).then(resp => {
    console.warn(resp);  // 新的值
    console.warn('4 =========<');
});

promise.then接受一个promise对象

  Promise.resolve('foo')
  //第一个promise已经resolve,将'foo'传入第一个then。
  .then(function(string) {
    return new Promise(function(resolve, reject) {
      setTimeout(function() {
        string += 'bar';
        resolve(string);
      }, 1000);//将1ms改为1s更易观察
    });
  })
// @1
  .then(function(string) {
    setTimeout(function() {
      string += 'baz';
      console.log(string);
    }, 1000)
    return string;
  })
//@2
  .then(function(string) {
    console.log("Last Then:  oops... didn't bother to instantiate and return " +
                "a promise in the prior then so the sequence may be a bit " +
                "surprising");
    console.log(string);
  });
  //由于第二个then中return的string值为'foobar',因此先输出'foobar'。
// 并在前面的1s定时结束后执行string += 'baz', 最后输出foobarbaz。
  • 第一个then中的函数返回一个promise对象,该promise对象状态为pending,根据‘如果then中的回调函数返回一个未定状态(pending)的Promise,那么then返回Promise的状态也是未定的,并且它的终态与那个Promise的终态相同;同时,它变为终态时调用的回调函数参数与那个Promise变为终态时的回调函数的参数是相同的。 ’摘自MDN。直到setTimeout时间到达,调用resolve(string),状态变为fulfilled(resolve),才调用下一个then方法。
  • 在第二个then中,先调用setTimeout(setTimeout调用定时器后不会等待计时完成,而是继续执行下面的代码, 在1s的定时结束后再将其中的程序加入任务队列),然后跳到return string,由于setTimeout内代码尚未执行,此时string == 'foobar'。且根据 ‘如果then中的回调函数返回一个值,那么then返回的Promise将会成为接受状态, 并且将返回的值作为接受状态的回调函数的参数值。’摘自MDN。 因此进入下一个then,且该段代码没有任何延时。

实现一个promise

class simplePromise {
    constructor(exec) {
        this.status = 'pending'
        this.value = undefined
        this.reason = undefined
        this.fullfillCalls = []
        this.rejectCalls = []
        let that = this
        function resolve(value) {
            // 状态只能从pending到 fullfilled 或者pending到rejected
            if (that.status !== 'pending') return
            // 真正的promise可能是通过其他延迟实现,
            // 我的理解是这里resolve并不会直接结束而是要去执行一些其他的同步语句
            // 如果有异步的话 可能要等待所有异步的完成?
            setTimeout(() => {
                that.status = 'fullfilled'
                that.value = value
                // then是可以连续回调的
                that.fullfillCalls.forEach(fn => fn && fn(value))
            })

        }
        function reject(error) {
            if (that.status !== 'pending') return
            setTimeout(() => {
                that.status = 'rejected'
                that.rejectCalls.forEach(fn => fn && fn(error))
            })

        }

        try {
            // 包装传递进来的函数,传递resolve 和reject函数
            exec(resolve, reject)
        } catch (error) {
            reject(error)
        }
    }  
        // 如果then必须返回一个promise对象,这也是能够链式调用的原因,
        // 如果是pending状态 那么返回的promise状态决定了调用者promise的状态
    then(onFullfill, onReject) {
        // 当then后面传入的不是函数 会被转化为函数?
        onFullfill = typeof onFullfill === 'function' ? onFullfill : value => value
        onReject = typeof onReject === 'function' ? onReject : reason => reason
        if (this.status === 'pending') {
            return new simplePromise((resolve, reject) => {
                this.fullfillCalls.push(onFullfill)
                this.rejectCalls.push(onReject)
            })
        // 当返回fullfilled状态 则立即执行fullfillCalls队列
        } else if (this.status === 'fullfilled') {
            onFullfill(this.value)
            // this.fullfillCalls.forEach(fn => fn && fn(this.value))
        } else if (this.status === 'rejected') {
            onReject(this.reason)
            // this.rejectCalls.forEach(fn => fn && fn(this.reason))
        }
    }
}
// 首先传入的函数被包裹到exec调用then函数,返回一个promise,将then后面的第一个函数压栈
// 等待setTimeout任务完成调用resolve,完成状态转化和函数执行
new simplePromise((resolve, reject) =>{
    setTimeout(() =>{
    resolve(123)
 })
 }).then(value =>{
    console.log(value)
 })

手动添加方法

Promise.prototype.done(callback){
   return this.then(
   value => {this.then(callback()).then(()=>value}
   reason => {this.then(callback()).then(() => throw reason)}
)
}
Array.prototype.add(number){
  return Array.prototype.concat.call(this, number)
}

相关文章

网友评论

      本文标题:promise.then

      本文链接:https://www.haomeiwen.com/subject/trwujhtx.html