说明
Node.JS 中, 以异步 (Async) 回调著称, 使用了异步, 提高了程序的执行效率, 但是, 代码可读性较差的.
假如有几个异步操作, 后一个操作需要前一个操作的执行完毕之后返回的数据才能执行下去, 如果使用 Node.JS, 就需要一层层嵌套下去, Promised 对象就是针对此问题所提出来的的解决办法.
基本概念
Promise 对象状态:
pending
初始状态, 也称为未定状态, 就是初始化 Promise 时, 调用 executor 执行器函数后的状态.
fulfilled
完成状态, 意味着异步操作成功.
rejected
失败状态, 意味着异步操作失败.
状态转换只有这两种 pending->fulfilled pending->, 可返回的这个 Promise 对象的状态主要是根据 promise1.then()方法返回的值:
状态转化是单向的, 不可逆转, 已经确定的状态 (fulfilled/rejected) 无法转回初始状态(pending)
当状态为 rejected, 该 promise 无法继续往下执行, 需要添加一个 catch 获得异常信息
回调函数:
resolve
当 pending 状态转为 fulfilled 状态时候回调(操作成功)
reject
当 pending 状态转为 rejected 状态时候回调(操作失败)
方法:
- then()
- catch()
- all()
- race()
基本使用
- new Promise(function(resolve,reject){
- // 这里面实现异步操作, Ajax 等..
- // 获得结果, 回调传参
- if(/*success*/){
- resolve();
- }else{
- reject();
- }
- });
- // 虽然没有去执行 setTimeOut 函数, 但是 Promise 会自动执行, 所以, 一般需要将 Promise 写在一个 function 里面
- new Promise(function(resolve,reject){
- setTimeout(function(){
- let num = Math.random();
- // 当随机数小于 0.5, 当前 promise 完成了执行
- if(num<0.5){
- resolve(num);
- }else{
- reject("错误, num>=0.5");
- }
- console.log('执行完成');
- },2000);
- });
- let p =new Promise(function(resolve,reject){
- setTimeout(function(){
- let num = Math.random();
- // 当随机数小于 0.5, 当前 promise 完成了执行
- if(num<0.5){
- resolve(num);
- }else{
- reject(num);
- }
- console.log('执行完成');
- },2000);
- });
- p.then(function(data){
- // 这里的 data 是之前 resolve 中的回调参数
- console.log(data);
- },function(error){
- // 这里的 error 是之前 resolve 中的回调参数
- console.log("错误原因为"+error);
- });
进阶使用
- then()
- Promise then(fun(resolve,reject))
- p.then(function(data){
- // 这里的 data 是之前 resolve 中的回调参数
- console.log(data);
- },function(data){
- // 这里的 data 是之前 resolve 中的回调参数
- console.log("错误");
- console.log(data);
- });
then 方法, 可以接收回调的参数并进行处理, then 方法返回的是一个 Promise 对象. 这里, 我们主要关心的是返回的 Promise 对象的状态.
可返回的这个 Promise 对象的状态主要是根据 promise1.then()方法返回的值:
如果 then()方法中返回了一个参数值, 那么返回的 Promise 将会变成接收状态.
如果 then()方法中抛出了一个异常, 那么返回的 Promise 将会变成拒绝状态.
如果 then()方法调用 resolve()方法, 那么返回的 Promise 将会变成接收状态.
如果 then()方法调用 reject()方法, 那么返回的 Promise 将会变成拒绝状态.
如果 then()方法返回了一个未知状态 (pending) 的 Promise 新实例, 那么返回的新 Promise 就是未知状态.
如果 then()方法没有明确指定的 resolve(data)/reject(data)/return data 时, 那么返回的新 Promise 就是接收状态, 可以一层一层地往下传递.
- let p =new Promise(function(resolve,reject){
- setTimeout(function(){
- let num = Math.random();
- // 当随机数小于 0.5, 当前 promise 完成了执行
- if(num<0.5){
- resolve(num);
- }else{
- reject(num);
- }
- console.log('执行完成');
- },2000);
- });
- p.then(function(data){
- // 用上次获得的数据执行相关的异步操作
- },function(error){
- // 出现错误, 处理错误信息
- });
- let p =new Promise(function(resolve,reject){
- setTimeout(function(){
- resolve("hello");
- console.log('执行完成');
- },2000);
- });
- p.then(function(data){
- console.log(data);
- }).then(function(){
- setTimeout(function(){
- console.log("过了 5s, 继续执行");
- },5000);
- });
- catch()
catch()方法和 then()方法一样, 都会返回一个新的 Promise 对象, 它主要用于捕获异步操作时出现的异常.
因此, 我们通常省略 then()方法的第二个参数, 把错误处理控制权转交给其后面的 catch()函数.
下面的两段代码块, 实现的功能是一样的.
- let p =new Promise(function(resolve,reject){
- setTimeout(function(){
- let num = Math.random();
- // 当随机数小于 0.5, 当前 promise 完成了执行
- if(num<0.5){
- resolve(num);
- }else{
- reject(num);
- }
- console.log('执行完成');
- },2000);
- });
- p.then(function(data){
- // 用上次获得的数据执行相关的异步操作
- },function(error){
- // 出现错误, 处理错误信息
- });
- let p =new Promise(function(resolve,reject){
- setTimeout(function(){
- let num = Math.random();
- if(num<0.5){
- resolve(num);
- }else{
- reject(num);
- }
- console.log('执行完成');
- },2000);
- });
- p.then(function(data){
- // 用上次获得的数据执行相关的异步操作
- }).catch(function(error){
- // 处理错误信息
- });
- race()
传入参数为可迭代的对象, 如数组
两个异步任务同时向同一个 url 发送请求, 谁先得到数据, 另外的那个异步任务获得的数据就会被丢弃
- //2s 后输出 "执行完成 1"
- let p =new Promise(function(resolve){
- setTimeout(function(){
- resolve("hello");
- console.log('执行完成 1');
- },2000);
- });
- //1s 后输出 "执行完成 2"
- let p1 =new Promise(function(resolve){
- setTimeout(function(){
- resolve("hello 2");
- console.log('执行完成 2');
- },1000);
- });
- // 两个异步任务同时开始
- let mixedPromisesArray = [p,p1];
- let p3 = Promise.race(mixedPromisesArray).then(data=>{
- // 这里的 data 为 hello 2,hello 被丢弃
- console.log(data);
- });
- all()
参数也是可迭代的对象, 如数组
一般用于几个任务同时并行运行的情况
当某个任务失败, 状态就会变为 reject
- //2s 后输出 "执行完成 1"
- let p =new Promise(function(resolve){
- setTimeout(function(){
- resolve("hello");
- console.log('执行完成 1');
- },2000);
- });
- //1s 后输出 "执行完成 2"
- let p1 =new Promise(function(resolve){
- setTimeout(function(){
- resolve("hello 2");
- console.log('执行完成 2');
- },1000);
- });
- // 两个异步任务同时开始
- let mixedPromisesArray = [p,p1];
- let p3 = Promise.all(mixedPromisesArray).then(data=>{
- // 这里的 data 数组, 存放着之前两个异步回调传的数据
- console.log(data);
- });
参考
ES6 关于 Promise 的用法
MDN Promise
来源: https://www.cnblogs.com/kexing/p/11246670.html