Promise对象--Mr.Ember

Promise对象--Mr.Ember

摘要

所谓promise,简单来说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)

 

promise对象有一下特点:

1. 对象的状态不受外界影响

2. 一旦状态改变就不会再变,任何时候都可以得到这个结果。

有了promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套函数。

 

Promise.prototype.then()

1.then方法下一次的输入需要上一次的输出
2.如果一个promise执行完后,返回的还是一个promise,会把这个promise的执行结果传递给下个then中
3.如果then中返回的不是Promise对象而是一个普通值,则会将这个结果作为下次then的成功结果
4.如果当前then中失败了 会走下一个then的失败
5.如果返回的是undefinded不管当前是成功还是失败,都会走下一次成功
6.catch是错误没有处理的情况下才会走
7.then中不写方法则会穿透,传入下一个then中
 
Promise.prototype.catch()
Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。
p.then((val) => console.log('fulfilled:', val))
    .catch((err) => console.log('rejected', err))
//等同于
p.then((val) => console.log('fulfilled:', val))
    .then(null, (err) => console.log('rejected', err))

 

Promise.all()

Promise.all将多个Promise实例包装成一个新的Promise实例。

var  p = Promise.all([p1, p2, p3]);

 

p的状态由p1,p2,p3决定,分为两种情况:
1. 只有p1, p2, p3的状态都为Fulfilled,p的状态才会变成Fulfilled,此时p1,p2,p3的返回值成一个数组,传递给p的回调函数。
2. 只要p1,p2,p3有一个被rejected,p的状态就会变成Rejected,此时第一个被rejected的实例的返回值会传递给p的回调函数。
 
Promise.race()
Promise.race也是将多个Promise实例包装成一个新的Promise实例。
var  p = Promise.all([p1, p2, p3]);

 上述代码中,只要p1, p2, p3有一个实例率先改变状态,p的状态就跟着改变。那个率先改变Promise的实例的返回值就传递给p的回调函数。

 

Promise.resolve()

有时需要将现有的对象转为Promise对象,Promise.resolve方法就起到了这个作用。

var jsPromise = Promise.resolve($ajax('/whatever.json'));

 

上面的代码会将JQ代码生成的deferred对象转换为新的promise对象。
 
Promise.reject()
Promise.reject会返回一个新的Promise实例,状态为Rejected
var p = Promise.reject('出错了')
//等同于
var p = new Promise((resolve, reject) => reject('出错了')

p.then(null, function(s){
  console.log(s)
})

 

Promise.done()

无论Promise对象的回调链以then的方法还是catch的方法结尾,只要最后一个放大抛出错误,都有可能无法捕捉到(因为Promise内部错误不会冒泡到全局)。为此我们可以提供一个done方法,它总是处于回调链的尾端,保证抛出任何可能出现的错误。

asyncFunc()
    .then(f1)
    .catch(r1)
    .then(f2)
    .done();

 

内部实现
Promise.prototype.done =  function (onFulfilled, onRejected) {
   this.then(onFulfilled, onRejected)
     .catch(function(reason) {
//全局抛出一个错误 setTimeout(()
=> {throw reson}, 0); }) }

 

Promise.finally()

finally方法用于指定Promise对象最后状态如何都会执行的操作。他与done的区别在于,它接受一个普通的回调函数作为参数,该函数不管什么状态都会执行。

 

模拟实现promise
实现步骤:
1.promise 有个then函数,需要有个callback函数来保存回调函数
2.可能会又多个resolve调用处理,添加一个开关变量,仅使第一个resolve函数可以使用
3.当出现多个then函数时,把callback属性改变成数组格式,保存每一个then的回调函数
4.支持then链式调用,执行完then函数后返回this即可
5.支持异步的链式调用,判断当前函数是个对象并且还有.then函数,需要继续调用then,否则跟原来一样调用
 
 
function MyPromise(fn) {
    var _this = this;

    //用来保存then传入的回调函数
    this.callback = [];
    //处理 第一个resolve有效
    this.isResolved = false;

    function resolve(val) {
        if(_this.isResolved) return;
        _this.isResolved = true;

        if(_this.callback.length > 0) {
            _this.callback.forEach(item => {
                // func && func(val)
                var res, cb = item.cb, resolve=item.resolve;

                cb && (res = cb(val))
                if(typeof res === 'object' && res.then) {
                    res.then(resolve)
                }else {
                    resolve && resolve(res)
                }
                
            });
        }
    }

    fn(resolve);
}

MyPromise.prototype.then = function(cb) {
    var _this = this;
    return new MyPromise(function(resolve) {
        _this.callback.push({
            cb: cb,
            resolve: resolve
        })
    })
}

var  p = new MyPromise(function(resolve) {
    console.log(1)
    setTimeout(function() {
        resolve(2)
        resolve(4)
        resolve(5)
        resolve(6)
    }, 1000)
})

p.then(function(val) {
    console.log(val)
    return new MyPromise(function(resolve) {
        setTimeout(function() {
            resolve(val + 1)
        }, 1000)
    })
}).then(function(val) {
    console.log(val)
})

 打印结果

 

 先打印1,过了一秒打印2,再过一秒打印3

 

转载于:https://www.cnblogs.com/teteWang-Ember/p/10375485.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值