一, 概念
(1)asychronous 异步
是 JS 这种单线程语言解决多任务的一种方法, 将耗时的任务 (io) 设定为异步工作, 先交给浏览器负责相关功能的线程来实现耗时的部分工作, 按顺序放入任务队列中, 等待主代码执行完成, 而主线程继续下一个任务, 不阻塞代码; 主线程任务完成后, 会收到浏览器的通知, 来实现异步任务的其他代码执行
===>事件循环 + 任务队列
(2)sychronous 同步
任务的执行是一个接着一个执行的, 上一个任务执行完成才能继续下一个任务, 有多个窗口, 进行一个接一个的执行任务
二, 异步有序问题
1, 回调 =====>回调地狱
当我们需要进行有序任务时, 最粗暴的方式就是用时间函数嵌套, 少个还可以分辨, 但若出现上百, 上千个事件呢? 如果任然使用这种方法, 就会形成 "回调地狱", 没有办法阅读处时间函数的时间对应的代码是哪一个:
- setTimeout(function () {
- console.log("a");
- setTimeout(function () {
- console.log("b");
- setTimeout(function () {
- console.log("c");
- setTimeout(function () {
- console.log("d");
- }, 1000)
- }, 2000)
- }, 1000)
- }, 1000)
于是乎, 我们的先人们捣鼓出了专门处理异步的方法.
2,Promise 承诺
首先, 我们来看一看 Promise 与上面的代码有什么不同
- new Promise(function (resolve, reject) {
- // console.log("a1");
- setTimeout(function () {
- console.log("a");
- resolve();
- }, 1000)
- }).then(() => {
- // return 1;// 下一个 then 被处罚时可以接收返回值
- return new Promise(function (resolve, reject) {
- // console.log("b1");
- setTimeout(function () {
- console.log("b");
- resolve();
- }, 2000)
- })
- }).then((data) => {
- return new Promise(function (resolve, reject) {
- // console.log("c1");
- setTimeout(function () {
- console.log("c",data);
- resolve();
- },3000)
- })
- })
我们可以看到, Promise 让每一个异步都是平行的了, 不再是嵌套关系, 语义化非常强, 让人一眼可以看出每个事件发生的顺序.
(1)使用 Promise 要注意状态值:
pending 已就绪 Promise 实例化的同时就已就绪, 状态只可改变 1 次, 且不可逆
resolved/fulfilled 已完成
rejected 已失败
===>状态改变, then 方法会触发 onfulfilled,onrejected 事件
(2)Promise 方法
我们分步骤来看, 是怎样应用的:
- new Promise(function(resolve,reject){});
- // 两个形参: resolve reject , 都是回调函数
- let fn1;
- let fn2;
- new Promise(function(resolve,reject){// 两个形参, 都是回调函数
- resolve();
- fn1 = resolve;
- fn2 = reject;
- });
resolve()方法会返回已完成状态, 就会触发 onfulfilled 事件, 让 then()代码走下去
若要写异步函数, 则将第一个异步函数卸写在在 Promise 里面, then()让后面的函数继续走
- p.then((data)=>{// 参数为 2 个事件监听器, 第一个是已成功时触发, 第二个是以失败时触发
- console.log("onfulfilled",data);
- },(data)=>{
- console.log("onrejected",data);//onrejected 触发且异常, 不报错
- })
- console.log(p);
- then :
返回值为 promise 对象, 初始状态是 pending
监听器被触发, 监听函数执行完成后, 返回值的状态发生改变
改变的情况由监听函数的执行返回值决定, 而具体情况参照 Promise.resolve(返回值)
then(onfulfilled,onrejected)含有两个参数, 都是事件监听器(函数), 第一个是已成功时触发, 第二个是以失败时触发. onrejected 触发且异常时, 不报错.
整体的代码就是:
- let fn1;
- let fn2;
- let p = new Promise(function(resolve,reject){// 两个形参, 都是回调函数
- resolve();
- // 第一个异步函数放在 Promise 里
- fn1 = resolve;
- fn2 = reject;
- });
- p.then((data)=>{// 参数为 2 个事件监听器, 第一个是已成功时触发, 第二个是以失败时触发
- console.log("onfulfilled",data);
- },(data)=>{
- console.log("onrejected",data);//onrejected 触发且异常, 不报错
- })
- console.log(p);
- (3)all(),race()
在 Promise 中有两个好用的方法, 就是 all(),race()
all()方法: 在所有异步代码都跑了后, 同时输出结果, 但结果显示顺序根据异步事件结束的先后来的
- let p1 = new Promise(function (resolve, reject) {
- console.log("a 开始了");
- setTimeout(function () {
- console.log("a");
- resolve();
- }, 4000)
- })
- let p2 = new Promise(function (resolve, reject) {
- console.log("b 开始了");
- setTimeout(function () {
- console.log("b");
- resolve();
- }, 3500)
- })
- let p3 = new Promise(function (resolve, reject) {
- console.log("c 开始了");
- setTimeout(function () {
- console.log("c");
- resolve();
- }, 5000)
- })
- let pp = Promise.all([p1,p2,p3]);
- pp.then(()=>{
- console.log("all");
- })
race()方法: 赛跑, 谁先结束谁先输出
- let p1 = new Promise(function (resolve, reject) {
- console.log("a 开始了");
- setTimeout(function () {
- console.log("a");
- resolve();
- }, 4000)
- })
- let p2 = new Promise(function (resolve, reject) {
- console.log("b 开始了");
- setTimeout(function () {
- console.log("b");
- resolve();
- }, 3500)
- })
- let p3 = new Promise(function (resolve, reject) {
- console.log("c 开始了");
- setTimeout(function () {
- console.log("c");
- resolve();
- }, 5000)
- })
- // let pp = Promise.all([p1,p2,p3]);
- // pp.then(()=>{
- // console.log("all");
- // })
- pp = Promise.race([p1,p2,p3]);
- pp.then(()=>{
- console.log("race");
- })
b 时间最短, 因此是 b 获胜
all,race 都生成 promise 对象, 但是状态的变化情况不一样
(4)返回值 return
Promise.value 通过 resolve 传递的参数
Promise.reslove(value)方法, 返回一个以给定值解析后的 Promise 对象
value 有三种情况:
普通值: 除了 promise 对象, 和 thenable 对象的所有值, 生成一个已完成的 promise 对象并且 PromiseValue 的值就是传入的 value
promise 对象, 直接返回该 value
thenable 对象, 参照 new Promise 生成的 promise 对象, 其中 then 方法就好比 new Promise(cb)中的 cb
在 then(data)中, data 就是 value 的值, 我们回到开头的那段代码:
- new Promise(function (resolve, reject) {
- // console.log("a1");
- setTimeout(function () {
- console.log("a");
- resolve();
- }, 1000)
- }).then(() => {
- // return 1;// 下一个 then 被处罚时可以接收返回值
- return new Promise(function (resolve, reject) {
- // console.log("b1");
- setTimeout(function () {
- console.log("b");
- resolve();
- }, 2000)
- })
- }).then((data) => {
- return new Promise(function (resolve, reject) {
- // console.log("c1");
- setTimeout(function () {
- console.log("c",data);
- resolve();
- },3000)
- })
- })
- then(() => {
- // return 1;// 下一个 then 被处罚时可以接收返回值, 大家可以自己去试一试.
浅谈 JS 异步(asychrouous)
来源: http://www.bubuko.com/infodetail-3333270.html