ES6-Promise下
六。实例的finally方法:
promise状态发生变化指的是由初始态变成成功或者失败态
处理错误指的是没有调用catch(失败态实例调用可以执行其回调的then)
finally里面的回调函数只要promise状态发生变化就会执行,但是接收不到参数
这里没有调用then方法,也会报错吗?什么时候报错?
应用场景:处理最终状态,比如js操作数据库,涉及异步操作,可以用promise,最终需要关闭数据库不论成功或者失败
finally的本质:
new Promise(function (resolve, reject) {
// resolve(1);
reject('reason');
}).finally(function () {
console.log(1);
});
// 相当于下面
new Promise(function (resolve, reject) {
// resolve(1);
reject('reason');
})
.then(
result => {
console.log(1);
return result;
},
err => {
console.log(1);
return new Promise(function (resolve, reject) {
reject(err);
});
}
);
finally源码
// 1.什么时候finally里面的回调执行
// 当 Promise 状态发生变化时,不论如何变化都会执行,不变化不执行
// new Promise((resolve, reject) => {
// // resolve(123);
// reject('reason');
// })
// .finally(data => {
// console.log(data);
// })
// .catch(err => {});
// 2.本质
// finally() 本质上是 then() 的特例
// new Promise((resolve, reject) => {
// // resolve(123);
// reject('reason');
// })
// .finally(data => {
// console.log(data);
// })
// .catch(err => {});
// 等同于
new Promise((resolve, reject) => {
// resolve(123);
reject('reason');
})
.then(
result => {
return result;
},
err => {
return new Promise((resolve, reject) => {
reject(err);
});
}
)
.then(data => {
console.log(data);
})
.catch(err => {
console.log(err);
});
七。构造函数Promise的方法
1.Promise.resolve()和Promise.reject()
注意,也不一定Promise.resolve()返回的就是成功状态p,看下面传有then方法的一般对象;
所以data接收的参数是p1实例里resolve的参数,也就是由p1接手了;
疑问:(前面已经解答)
解释为什么有这两个函数
同步异步定时器问题,去掉return问题前面的,为什么有的等1秒,有的不等
注意,挂起的then里面的回调会等当前的正在主车道执行的代码执行完再执行;
源码
<script>
// 1.Promise.resolve()
// 是成功状态 Promise 的一种简写形式
// new Promise(resolve => resolve('foo'));
// // 简写
// Promise.resolve('foo');
// 参数
// 一般参数
// Promise.resolve('foo').then(data => {
// console.log(data);
// });
// Promise
// 当 Promise.resolve() 接收的是 Promise 对象时,直接返回这个 Promise 对象,什么都不做
// const p1 = new Promise(resolve => {
// setTimeout(resolve, 1000, '我执行了');
// // setTimeout(() => {
// // resolve('我执行了');
// // }, 1000);
// });
// Promise.resolve(p1).then(data => {
// console.log(data);
// });
// 等价于
// p1.then(data => {
// console.log(data);
// });
// console.log(Promise.resolve(p1) === p1);
// 当 resolve 函数接收的是 Promise 对象时,后面的 then 会根据传递的 Promise 对象的状态变化决定执行哪一个回调
// new Promise(resolve => resolve(p1)).then(data => {
// console.log(data);
// });
// 具有 then 方法的对象
// function func(obj) {
// obj.then(1, 2);
// }
// func({
// then(resolve, reject) {
// console.log(a, b);
// }
// });
// const thenable = {
// then(resolve, reject) {
// console.log('then');
// resolve('data');
// // reject('reason');
// }
// };
// Promise.resolve(thenable).then(
// data => console.log(data),
// err => console.log(err)
// );
// console.log(Promise.resolve(thenable));
// 2.Promise.reject()
// 失败状态 Promise 的一种简写形式
// new Promise((resolve, reject) => {
// reject('reason');
// });
// 等价于
// Promise.reject('reason');
// 参数
// 不管什么参数,都会原封不动地向后传递,作为后续方法的参数
// const p1 = new Promise(resolve => {
// setTimeout(resolve, 1000, '我执行了');
// });
// Promise.reject(p1).catch(err => console.log(err));
new Promise((resolve, rejcet) => {
resolve(123);
})
.then(data => {
// return data;
// return Promise.resolve(data);
return Promise.reject('reason');
})
.then(data => {
console.log(data);
})
.catch(err => console.log(err));
</script>
2.Promise.all()方法
注意,参数里面有rejected实例的情况,只要根据代码执行顺序识别到有一个rejected实例,那么下图的p就变成失败态且接收识别到的失败态reject里面的参数a
等价于const p = Promise.reject(a),p和识别的那个rejected实例不是一个实例,只是参数和状态一样;
还有p由p1p2决定,p1p2赋值还未完成,所以p的赋值也未完成,同步执行时,定时器还没执行,delay函数return出去的也是暂时的,所以pp1p2也是暂时的pending状态,异步执行完毕,return后面的值刷新,delay(1000)delay(2000)的返回值也刷新,pp1p2的赋值也刷新;
如果all里面参数若为空数组的话,默认返回实例状态为成功
<script>
// 1.有什么用
// Promise.all() 关注多个 Promise 对象的状态变化
// 传入多个 Promise 实例,包装成一个新的 Promise 实例返回
// 2.基本用法
const delay = ms => {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
};
const p1 = delay(1000).then(() => {
console.log('p1 完成了');
// return 'p1';
return Promise.reject('reason');
});
const p2 = delay(2000).then(() => {
console.log('p2 完成了');
return 'p2';
// return Promise.reject('reason');
});
// Promise.all() 的状态变化与所有传入的 Promise 实例对象状态有关
// 所有状态都变成 resolved,最终的状态才会变成 resolved
// 只要有一个变成 rejected,最终的状态就变成 rejected
const p = Promise.all([p1, p2]);
p.then(
data => {
console.log(data);
},
err => {
console.log(err);
}
);
</script>
<script>
const delay = ms => {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
};
const p1 = delay(1000).then(() => {
console.log('p1 完成了');
return 'p1';
// return Promise.reject('reason');
});
const p2 = delay(2000).then(() => {
console.log('p2 完成了');
// return 'p2';
return Promise.reject('reason');
});
// 1.Promise.race()
// Promise.race() 的状态取决于第一个完成的 Promise 实例对象,如果第一个完成的成功了,那最终的就成功;如果第一个完成的失败了,那最终的就失败
// const racePromise = Promise.race([p1, p2]);
// racePromise.then(
// data => {
// console.log(data);
// },
// err => {
// console.log(err);
// }
// );
// 2.Promise.allSettled()
// Promise.allSettled() 的状态与传入的Promise 状态无关
// 永远都是成功的
// 它只会忠实的记录下各个 Promise 的表现
const allSettledPromise = Promise.allSettled([p1, p2]);
allSettledPromise.then(data => {
console.log('succ', data);
});
</script>
<script>
// 1.resolve 或 reject 函数执行后的代码
// 推荐在调用 resolve 或 reject 函数的时候加上 return,不再执行它们后面的代码
// new Promise((resolve, reject) => {
// // return resolve(123);
// return reject('reason');
// console.log('hi');
// });
// 2.Promise.all/race/allSettled 的参数问题
// 参数如果不是 Promise 数组,会将不是 Promise 的数组元素转变成 Promise 对象
// Promise.all([1, 2, 3]).then(datas => {
// console.log(datas);
// });
// 等价于
// Promise.all([
// Promise.resolve(1),
// Promise.resolve(2),
// Promise.resolve(3)
// ]).then(datas => {
// console.log(datas);
// });
// 不只是数组,任何可遍历的都可以作为参数
// 数组、字符串、Set、Map、NodeList、arguments
// Promise.all(new Set([1, 2, 3])).then(datas => {
// console.log(datas);
// });
// 3.Promise.all/race/allSettled 的错误处理
const delay = ms => {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
};
const p1 = delay(1000).then(() => {
console.log('p1 完成了');
// return 'p1';
return Promise.reject('reason');
});
// .catch(err => {
// console.log('p1', err);
// });
const p2 = delay(2000).then(() => {
console.log('p2 完成了');
return 'p2';
// return Promise.reject('reason');
});
// // .catch(err => {
// // console.log('p2', err);
// });
const allPromise = Promise.all([p1, p2]);
allPromise
.then(datas => {
console.log(datas);
})
.catch(err => console.log(err));
// 错误既可以单独处理,也可以统一处理
// 一旦被处理,就不会在其他地方再处理一遍
</script>
九。promise应用
异步加载图片,停留在当前图片时,趁这个时间浏览器从服务器端加载其他资源,图片,然后点击切换按钮想要切换图片时,就可以显示到页面(通过dom),并不是点击切换才去服务器端加载这个图片
promise里的回调一般不写逻辑,一般写的是什么时候调用resolve或者reject;
如果不用promise的话,就会加两个形参接收回调函数,一个负责图片加载成功该怎么办,一个负责图片加载失败
注意img这里是个对象,是Image构造出来的实例,和dom对象没关系
注意这里的SRC属性是实例img的属性和html dom元素的SRC属性不一样
const img = new Image()只是实例化创建了一个img标签,也可以通过appendchild加入到html结构里
注意img.src=url,src属性值变化就能触发onload和onerror事件,img.src=url这个代码的作用就是一个工具,作用是像服务端发请求拿资源,这就是异步加载图片;
如果传进来的url并没有请求到图片,就会触发error事件
实际开发过程中,可能是点击按钮才切换图片;
如果图片加载失败(url错误)会有这个提示:
<style>
#img {
width: 80%;
padding: 10%;
}
</style>
</head>
<body>
<img
src="https://img.mukewang.com/5e6af63d00011da318720764.jpg"
alt=""
id="img"
/>
<script>
// 异步加载图片
const loadImgAsync = url => {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
resolve(img);
};
img.onerror = () => {
reject(new Error(`Could not load image at ${url}`));
};
img.src = url;
});
};
const imgDOM = document.getElementById('img');
loadImgAsync('https://2img.mukewang.com/5f057a6a0001f4f918720764.jpg')
.then(img => {
console.log(img.src);
setTimeout(() => {
imgDOM.src = img.src;
}, 1000);
})
.catch(err => {
console.log(err);
});
</script>
①代码执行loadImgAsync('https://2img.mukewang.com/5f057a6a0001f4f918720764.jpg')时,就会创建img对象,并给img对象赋予具体的src地址:
②此时就会开启网络请求,去网络中某一个具体的位置请求图片,即异步加载图片。图片加载完,就会继续执行如下:
由于图片所在的服务器响应特别快,并且我们的网络特别给力、电脑性能也特别好,因此加载图片这个异步过程会迅速完成,看上去和使用本地图片一样快。但是假设图片所在的服务器响应很慢,那么图片就会很慢的请求回来,举个常见的现象:某些网站,打开后,图片迟迟不展示,此时速度上,就有差异了。
十。如何统一处理错误?Promise参与过程中什么时候会报错?Promise.all等方法返回值是新的promise实例,和传进来的无关;
1.如何统一处理错误:
------------------------------------------------------------------------------------------------------------------------------------------------------
十一。async和await (使得异步操作变得更加方便。)
async
表示函数里有异步操作,await
表示紧跟在后面的表达式需要等待结果。
调用async
函数时,会立即返回一个Promise
对象。
注意await后面放的是一个可以求值的东西(函数调用等)
等待Promise返回结果: ,如果跟的是promise实例这种情况,会等Promise实例过程中的所有代码全部执行完毕(不论同步异步)如果最终状态为成功态,执行该函数体后面的代码(打印end)
如果最终是失败态实例,该函数体后面的代码(打印end)不会执行且会报错;如果最终是pending状态,该函数体后面的代码(打印end)也不会执行
最新文章
- bzoj4443[SCOI2015]小凸玩矩阵
- UP board 漫谈(1)——从Atom到UP Board
- AutoMapper搬运工之自定义类型转换
- Activity类生命周期
- elasticsearch单机多实例环境部署
- Entity Framework 自动生成CodeFirst代码
- Quartz将Job保存在数据库中所需表的说明
- pouchdb Conflicts
- sdfsdf
- hdu_5904_LCIS(DP)
- 用JavaScript实现图片剪切效果
- SK-Learn 全家福
- 创建一个servlet
- Fiddler使用简单介绍
- Webpack vs Browersify vs SystemJs for SPAs
- Ribbon
- 6. go数组与冒泡排序
- 使整个页面变灰的css代码
- 解决Struts2 json-plugin Date或Timestamp等日期格式带T的问题
- [JSOI2018]潜入行动
热门文章
- 学习Vue过程中遇到的问题---code: &#39;MODULE_NOT_FOUND&#39;
- CF1418D Trash Problem
- 我做的FFmpeg开源C#封装库Sdcb.FFmpeg
- 06#Web 实战:可滑动的标签页
- Sequelize.js + Express.js 开发 API
- Canvas:绘制矩形
- Lambda表达式和Collection集合
- MicroPython 之 PYBoard
- [NPUCTF2020]EzRSA
- Chisel项目中,添加了一个文件,新增了一个模块,但是却编译不出来相应的.v文件,什么原因?