promise

Promise 是异步编程的一种解决方案,与传统的回调函数和事件相比,Promise的优点是代码可以让我们更容易理解,我们可以更加清晰的知道代码的走向,避免回调函数嵌套陷入回调地狱中。

一、三种状态

Pending(进行中)、Resolved(已完成,又称 Fulfilled)和Rejected(已失败),Promise的状态只能从Pending 变为Resolved 或者从Pending 变为 Rejected
即使改变已经发生,而且当时并没有为Promise添加回调函数,之后再为Promise添加回调函数依然会执行,这和事件回调函数完全不同。

二、常见用法
1.Promise

创建一个promise实例:

    var p1=new Promise((resolve,reject)=>{
        setTimeout(()=>{
            reject(0);
        },5000)
    });

Promise构造函数接受一个函数作为参数,函数的第一个参数(resolve)将promise状态从pending变成resolved(成功),第二个参数(reject)将状态从pending变成rejected(失败)。

2. then

then方法接受两个函数作为参数,分别作为promise状态变为resolved和rejected时的回调函数:

p1.then((data)=>{
    console.log(`resolve${data}`);
},e=>{
    console.log(`reject-${e}`);
})

结果:reject-0

then方法返回的仍然是一个Promise对象,可以继续调用then方法,新的then方法接受的数据是前一个的返回值

var p1=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        reject(0);
    },5000)
});
p1.then((data)=>{
    console.log(`resolve${data}`);
},e=>{
    console.log(`reject-${e}`);
})
.then(data=>{
    console.log(`resolve2-${data}`)
},e=>{
    console.log(`reject2-${e}`)
});

结果:
reject-0
resolve2-undefined

因为我们第一个then方法没有return任何值,所以第二个输出是undefined。
我们发现即使第一个then方法调用的是rejected状态的回调,但是第二个then方法仍然调用了resolved状态的回调,其实只要then方法没有throw Error,后面的then方法都会执行resolved状态,如果抛出异常就会执行rejected

3.catch

当promise操作及then方法的过程中抛出异常,promise状态就变成了rejected。此时走接下来then中的rejected,如果仅仅为了处理异常,接下来的then方法可以这样写:

p1.then(null,reject)

reject接受的是抛出的异常信息,catch方法就是这种写法的简写:

p1.catch(reject)

如果Promise状态已经变成Resolved,再抛出错误是无效的。因为Promise 的状态一旦改变,就永久保持该状态,不会再变了
Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止,只要被捕获就不会继续传递(注意:catch和then中的reject方法是一样的,两者都可以捕获异常),所以我们可以在then中不写reject,在最后一个then后面写catch
Promise中的异常及时不处理也不会引起程序异常

4.Promise.all([p1,p2,p3…])

Promise.all接受一个Promise实例数组,如果不是,就会先调用Promise.resolve方法转为Promise实例。
var p = Promise.all([p1, p2, p3]);
此时p的状态由所有的Promise实例参数的状态所决定:

    1. 如果所有的状态都是resolved,则p是resolved,p的返回值是所有实例返回值组成的数组,数组的顺序和定义p时的顺序一致
    2. 如果有一个参数的状态是rejected,则p的状态是rejected,p的返回值是第一个状态为rejected的实例的返回值,也是数组形式

例1:

var p1=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('p1');
    },2000)
}).then(data=>{return 'p2';});

Promise.all([p1,22,33,44,55])
.then(data=>{
    console.log(data);
},(e)=>{
    console.log(e);
});

结果:
[ 'p2', 22, 33, 44, 55 ]

我们可以看到返回值是一个数组,而且p1的返回值是最终then的返回值,不是仅仅Promise实例时的值

例2:

var p1=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('p1');
    },2000)
}).then(data=>{
    throw Error(`p1 is wrong`);
});
var p2=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('p2');
    },1000)
}).then(data=>{
    throw Error(`p2 is wrong`);
});

Promise.all([p1,p2,33,44,55])
    .then(data=>{
        console.log(data);
    },(e)=>{
        console.log(e);
    });
结果:
[Error: p2 is wrong]

因为p1,p2状态为rejected,而且p2 1s延迟先执行完,所以结果为p2的返回值。

5. Promise.race([p1,p2,p3…])

Promise.race方法同样是将多个Promise实例,包装成一个新的Promise实例。
var p = Promise.race([p1, p2, p3]);
Promise.racePromise.all 接受的参数一样,不是Promise实例也会先resolve转换。
Promise.race与名字一样,多个实例就像在赛跑一样,谁先执行完毕最后p的状态就是那个先执行完毕的,那个率先改变的 Promise 实例的返回值,就传递给p的回调函数
例1:

var p1=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('p1');
    },2000)
}).then(data=>{
    // throw Error(`p1 is wrong`);
    return 'p11111';
});
var p2=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('p2');
    },1000)
}).then(data=>{
    // throw Error(`p2 is wrong`);
    return 'p222222';
});

Promise.race([p1,p2,33,44,55])
    .then(data=>{
        console.log(data);
    },(e)=>{
        console.log(e);
    });

    结果:
    33

所有实例状态都是resolved,但是p1、p2都有延迟,所以第三个先执行完。

例2:

var p1=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('p1');
    },2000)
}).then(data=>{
    throw Error(`p1 is wrong`);
});
var p2=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('p2');
    },1000)
}).then(data=>{
    throw Error(`p2 is wrong`);
});
var p3=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('p3');
    },1000)
});

Promise.race([p1,p2,p3])
    .then(data=>{
        console.log(data);
    },(e)=>{
        console.log(`catch:${e}`);
    });
结果:
catch:Error: p2 is wrong

因为p2先执行完切抛出异常,所以p最后状态也是rejected,接受p2返回值

参考阮一峰ECMAScript 6 入门

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值