深入理解Promise以及最新方法

Promise所有方法

Promise 必须为以下三种状态之一:等待态(Pending)、执行态(Fulfilled)和拒绝态(Rejected)。一旦Promise 被 resolve 或 reject,不能再迁移至其他任何状态(即状态 immutable)


前言

Promise构造函数接受一个函数作为参数
resolve 将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),
reject 将Promise对象的状态从“未完成”变为“失敗”(即从Pending变为Rejected),
then方法可以接受两个回调函数作为参数 ,第一个回调函数是Promise对象的状态变为Resolved时调用,第二个回调函数是Promise对象的状态变为 Reject时调用,第二参数可选,这两个函数都接受Promise对象传出的值作为参数

一、Promise是什么?

Promise 是异步的解决方案,也是异步编程的选择

Promise使用步骤

1.实例化Promise

代码如下(示例):

function func(data) {
  return new Promise((resolve, reject) => {
    data ? resolve(data) : reject({ msg: "Promise失敗的", data });
  });
}

2.then方法

then方法是定义在原型对象Promise.prototype上的 Promise实例添加状态改变时的回调函数

func()
  .then(
    (data) => {
      console.log(data, 1);
    },
    (err) => {
      console.log(err, 2);
    }
  )
  .catch((err) => {
    console.log(err, 1);
  });

3.链式操作

var p1 = new Promise((resolve, reject) => {

  resolve(1);
});
var p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(p1);
  }, 1000);
});

then方法返回的是一个新的Promise实例

p2(1)
  .then(
    (data) => {
      console.log("resolve", data);
    },
    (err) => {
      console.log("p2的错误对象", err);
    }
  )
  .then((d) => {
    console.log(d);
  });

3.链式操作返回值

let p1 = new Promise((resolve, reject) => {
  resolve(886);
  })
p1.then(data=>{
return data+4; //886+4
}).then(data2=>{ 
console.log(data2); // 889
})

p1 返回为886第一个then拿到数据后在本身数据加了4并返回出去,在第二个the 拿到的值为 886+4 为889

拒绝处理也可以使用上面操作返回值
let p1 = new Promise((resolve, reject) => {
  reject(886);
  })
p1.catch(data=>{
return data+4; //886+4
}).catch(data2=>{ 
console.log(data2); // 889
})

Promise 返回 Promise

let p1 = new Promise((resolve, reject) => {
  resolve(66);
});

let p2 = new Promise((resolve, reject) => {
  resolve(88);
});

p1.then((result) => {
  console.log(result);
  return p2;
}).then((data) => {
    console.log(data);
  })
  .catch((err) => {});

p1 返回的是成功的 在then 可以得到 66 的返回值 因为then 函数 可以链式操作,所有这里返回的是 p2 (但是这个p2 是成功的状态 这里可以直接把p2看着88 前提必须在then 函数里面,后面并且还有then来接收上一个then的返回的值
如果p2 是一个reject的 则触发catch 函数

拆分上面的 p1 和p2
let p1 = new Promise((resolve, reject) => {
  resolve(66);
});

let p2 = new Promise((resolve, reject) => {
  resolve(88);
});

let p3 = p1.then((data) => {
  console.log(data);//66
  return p2;
});

p3.then((data) => {
  console.log(data); //88
});

这里有一个明显的一点是 p2 完成是p3 这个变量来接收的 p2的返回值,而p3这个时候就可以使用then因为p2返回的是一个Promise

如果 p2 是拒绝处理的,并且又没有去处理这个错误 分别在NodeJS 和浏览器都会抛出异常

浏览器中
unhandledrejection 事件循环中
rejectionhandled 在一个事件循环后
NodeJS中触发
unhandledRejection 事件循环中触发
rejectionHandled 在一个事件循环后

let p1 = new Promise((resolve, reject) => {
  resolve(66);
});

let p2 = new Promise((resolve, reject) => {
  reject(88);
});

p1.then((result) => {
  console.log(result);
  return p2;
}).then((data) => {
  console.log(data);
});

错误在Node环境出现以下错误

(node:17384)
UnhandledPromiseRejectionWarning: 88
(Use node --trace-warnings ... to show where the warning was created)
(node:17384) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:17384) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

错误在浏览器中错误

Uncaught (in promise) 88

没有解决的错误处理都有一个特点 都是可以看见是 88 这个reject抛出来的错误

Promise 并发 all ,race,allSettled,any

Promise.all()

必须所有的成功才会成功 一个失败所有都会失败

let p1 = new Promise((resolve, reject) => {
  resolve(66);
});

let p2 = new Promise((resolve, reject) => {
  resolve(77);
});

let p3 = new Promise((resolve, reject) => {
  resolve(88);
});

let p4 = new Promise((resolve, reject) => {
  resolve(99);
});

let all = Promise.all([p1, p2, p3, p4]);

all.then((data) => {
  console.log(data); // [ 66, 77, 88, 99 ]
});

Promise.all() 返回的是数组 并且是数组里面是resolve的值

一个Promise拒绝处理,后面所有都拒绝处理

let p1 = new Promise((resolve, reject) => {
  resolve(66);
});

let p2 = new Promise((resolve, reject) => {
  resolve(77);
});

let p3 = new Promise((resolve, reject) => {
  resolve(88);
});

let p4 = new Promise((resolve, reject) => {
  reject(99);
});

let all = Promise.all([p1, p2, p3, p4]);

all
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err); //99
  });
Promise.race()

Promise.race()跟Promise.all() 相似,但是不同的是会

let p1 = new Promise((resolve, reject) => {
  resolve(66);
});

let p2 = new Promise((resolve, reject) => {
  resolve(77);
});

let p3 = new Promise((resolve, reject) => {
  resolve(88);
});

let all = Promise.race([p1, p2, p3]);

all
  .then((data) => {
    console.log(data); // 66
  })
  .catch((err) => {
    console.log(err);
  });

使用setTimeout测试

let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(66);
  }, 3);
});

let p3 = new Promise((resolve, reject) => {
//setTimeout 第3个参数是传递到 第一个参数(函数)的形参
  setTimeout( (data) => {
      resolve(data);
    }, 2,88);
});

let all = Promise.race([p1, p3]);
all
  .then((data) => {
    console.log(data); // 88
  })
  .catch((err) => {
    console.log(err);
  });

同样的是如果其中有没有被处理(reject触发)都会没有值

Promise.allSettled()

该方法接收一个数组,并且数组里面是Promise待执行,该方法跟all 差不多,区别再去,会等待里面所有Promise 有结果才会响应,并且返回的是数组,
方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果

在这里插入图片描述

let p1 = new Promise((resolve, reject) => {
  resolve(66);
});

let p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(77);
  }, 2000);
});

let p3 = new Promise((resolve, reject) => {
  reject(88);
});
let p4 = new Promise((resolve, reject) => {
  throw new Error('故意的')
});


let all = Promise.allSettled([p1, p2, p3, p4]);

all.then((data) => {
  console.log(data); 
}).catch((err) => {
  console.log(err);
});

浏览器中
在这里插入图片描述
NodeJS中
在这里插入图片描述

这里可以看出来,是返回的数组并且是可以迭代的数组,分别有二个状态 fulfilledy和 rejected
如果 Promise 直接抛出出错,rejected 则有 data[3].reason.message 这个错误描述 如果错误被reject返回出来状态则为rejected 错误描述为item.reason

all.then((data) => {
  data.forEach(item => {
    item.status === 'fulfilled' && console.log(item.status, item.value);
    item.status === 'rejected' && console.log(item.status, item.reason.message || item.reason);
  })
}).catch((err) => {
  console.log(err);
});

在这里插入图片描述

Promise.any

在这里插入图片描述

当我们只需要一个 promise 成功,而不关心是哪一个成功时此方法很有用的
any知道ts的,any 为任意,这里的any 标识其中一个成功则成功
方法用于返回第一个成功的 promise 。只要有一个 promise 成功此方法就会终止,它不会等待其他的 promise 全部完成。
不像 Promise.all() ,会等待所以的执行完后才会返回一组完成值
也不像 Promise.race() 总是返回第一个结果值(resolved/reject)那样,这个方法返回的是第一个 成功的 值。这个方法将会忽略掉所有被拒绝的 promise,直到第一个 promise 成功

const pErr = new Promise((resolve, reject) => {
  reject("总是失败");
});

const pSlow = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, "最终完成");
});

const pFast = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "很快完成");
});

Promise.any([pErr, pSlow, pFast]).then((value) => {
  console.log(value);
})

如果一个都没有成功则触发异常



const pErr = new Promise((resolve, reject) => {
  reject("失败");
});

const pSlow = new Promise((resolve, reject) => {
  setTimeout(reject, 500, "最终完成");
});

const pFast = new Promise((resolve, reject) => {
  setTimeout(reject, 100, "很快完成");
});

Promise.any([pErr, pSlow, pFast]).then((value) => {
  console.log(value);
}).catch(err=>{
console.error(err); // All promises were rejected
})

Promise继承
class newPromise extends Promise {
  success(resolve, reject) {
    return this.then(resolve, reject);
  }
  failure(reject) {
    return this.catch(reject);
  }
}

const newP = new newPromise((resolve, reject) => {
  reject(199);
  resolve(99);
});

newP.success((data) => {
    console.log(data);
  })
  .failure((err) => {
    console.error(err); //199
  });
console.log(newP); //newPromise [Promise] { 99 }

我们自定义了一个newPromise的类,并且继承Promise,newPromise上扩展了二个方法success,以及failure,success模仿了 then函数 ,failure模仿了catch函数,因为是继承过来的Promise,所有我们能够在newPromise 这个类里面使用 Promise 所有东西,使用this 就能访问原有Promise所有的方法

extends 可以继承任何比如说 Array 数组的操作,可以自定义扩展方法

在这里插入图片描述

4.全局的错误处理

Nodejs错误处理

在Node.js 中处理Promise拒绝时会触发 process对象到二个是件
1.unhandlerejection 在一个时间循环中,当Promise 被拒绝,并且没有提供错误处理方法,就会触发该事件

  • unhandledrejection 继承自 PromiseRejectionEvent,而 PromiseRejectionEvent 又继承自 Event。因此unhandledrejection 含有 PromiseRejectionEvent 和 Event 的属性和方法。
2.'rejectionHandled' 事件 在事件循环后 当Promise 被拒绝时,若拒绝处理程序被调用 就触发该事件

设计这些事件是用来识别那些被拒绝却又没有被处理的Promise

下面演示一下 unhandledRejection

let Rejected;

process.on("unhandledRejection", (reason, promise) => {
  console.log("=====", reason.message);

  console.log("0000..", promise);
});

Rejected = Promise.reject(new Error("手写BUG"));

在这里插入图片描述
下面演示一下 rejectionHandled

let Rejected;

process.on("rejectionHandled", (reason, promise) => {
  console.log(Rejected === promise);
});

Rejected = Promise.reject(new Error("手写BUG"));

setTimeout(() => {
  Rejected.catch((val) => {
    console.log(" Rejected.catch", val.message);
  });
}, 2000);

在这里插入图片描述
这里 rejectionHandled 事件在拒绝处理程序最后被调用触发,如果在rejected 直接添加错误处理程序,那么rejectionHandled 就不会触发 因为 rejected创建的过程与错误处理程序的调用在一个事件循环中,此时rejectionHandled事件尚未生效

收集Node中的Promise错误没有被处理的函数

const EventPollingPromiseError = (hadeleRejection:Function)=>{

  let poccibyUnhandledRejection = new Map();
  process.on("unhandledRejection", (reason, promise) => {
    poccibyUnhandledRejection.set(reason, promise);
  });

  process.on("rejectionHandled", (promise) => {
    poccibyUnhandledRejection.delete(promise);
  });

  setInterval(() => {
    poccibyUnhandledRejection.forEach((reason, promise) => {
      console.log(reason.message ? reason.message : reason);
      hadeleRejection(promise,reason)
    });

    poccibyUnhandledRejection.clear();
  }, 6000);

};

浏览器错误处理

unhandledrejection 在一个事件循环中 当Promise被拒绝,并没有提供错误处理的时候触发

rejectionhandled 在一个事件循环后,当Promise被拒绝 若拒绝处理被调用,就触发该事件

在Nodejs 中 事件处理程序接收多个独立的参数,在浏览器中事件处理程序接受以下属性的事件对象作为参数,

事件名描述
type事件名称(onunhandledrejection或者,onrejectionhandled )
promise被拒绝的Promise
reason来自Peomise拒绝的值

浏览器实现的另一处不同的是,在二个事件中都可以使用拒绝值 reason


    let Rejected;
    window.onunhandledrejection = (event) => {
        console.log(event);
        console.log(event.reason);
        console.log(event.reason);
        console.log(Rejected === event);
    };

    window.onrejectionhandled = (event) => {
        console.log(event);
    };

    Rejected = Promise.reject(new Error("手写BUG"));

在这里插入图片描述

收集浏览器中Promise错误没有被处理的函数

const browserEventTopPromiseError = (hadeleRejection:Function)=>{
  let poccibyunhandledRejection = new Map();

  window.onunhandledrejection =  (event:any) => {
    poccibyunhandledRejection.set(event.promise, event.reason);
  };

  window.onrejectionhandled  = (event:any) => {
    poccibyunhandledRejection.delete(event.promise);
  };

  setInterval(() => {
    poccibyunhandledRejection.forEach((reason, promise) => {
      console.log(reason.message ? reason.message : reason);
      hadeleRejection(promise,reason)
    });

    poccibyunhandledRejection.clear();
  }, 6000);
}

该处使用的url网络请求的数据。

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值