Promise用法
Promise,简单来说就是一个容器,里面保存着某个未来才会结束的时间(通常是一个异步操作的结果)
Promise.race 返回第一个结果
let p1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('success')}, 1000)})let p2 = new Promise((resolve, reject) => {setTimeout(() => {resolve('failed')}, 500)})Promise.race([p1, p2]).then((result) => {console.log('result:' + result) //返回的是 result:success}).catch((error) => {console.log('error:' + error)})
Promise.all 返回所有结果,是一个数组。
let p1 = new Promise((resolve, reject) => {resolve(['成功了1','成功了2'])})let p2 = new Promise((resolve, reject) => {resolve('success')})let p3 = Promise.reject('失败')Promise.all([p1, p2]).then((result) => {console.log(result) //['成功了', 'success']}).catch((error) => {console.log(error)})Promise.all([p1, p3, p2]).then((result) => {console.log(result)}).catch((error) => {console.log(error) // 失败了,打出 '失败'})
异步编程的最高境界就是不关心它是否是异步。async、await很好的解决了这一点,将异步强行转换为同步处理。
async/await与promise不存在谁代替谁的说法,因为async/await是寄生于Promise一起使用。
Promise和anysc await 配合使用,下面代码在1之后的3秒打印success,将异步返回的结果,变成同步使用。
let p = new Promise((resolve, reject) => {setTimeout(() => {resolve('success');}, 3000);});async function demo(params) {try {console.log(1);let result = await p;console.log(result);} catch (e) {console.log(e);}}demo();
宏任务(macro-task):整体代码script、setTimeOut、setInterval
微任务(mincro-task):promise.then、promise.nextTick(node)
Promise执行顺序优先于timeout函数。前一个宏任务中的微任务执行优先级,大于下一个宏任务。
function timeOut() {// return new Promise((resolve, reject) => {setTimeout(() => {// reject('图片请求超时');console.log('timeOut');}, 0)// })}function getImg() {return new Promise((resolve, reject) => {const oImg = new Image();oImg.onload = function () {resolve(oImg);}// oImg.src = 'https://cdn.eso.org/images/screen/eso1242a.jpg';oImg.src ='https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fx0.ifengimg.com%2Fucms%2F2020_52%2F8895766234F132AFEB5FD6A199F7CE8F073F606D_size1264_w3000_h1999.jpg&refer=http%3A%2F%2Fx0.ifengimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1611230218&t=7b72eaa577445e0d7c618dae12a9d511';console.log('getImg');})}function testTwo() {getImg();timeOut();console.log('同步方法');}testTwo();Promise.race([getImg(),timeOut()]).then((res) => {console.log(666);}).catch((err) => {console.log(err);})
js运行机制
js执行上下文核心思想:首先执行同步任务,然后执行异步任务,异步任务包含(微任务,宏任务)。
setTimeout(function () {console.log(1);}, 0);console.log(2);let res = new Promise((resolve, reject) => {console.log(3);resolve();}).then(function () {console.log('4.我是新增的微任务');})console.log(5);setTimeout(function () {console.log(6);}, 0);
上述代码,先执行同步任务,打印2,然后执行Promise中的3,继续打印5,然后执行微任务4,当前同步任务,以及这条线上的微任务都执行完毕。继续执行下一个宏任务setTimeout。
思考案例
setTimeout(function () {console.log(1);let res = new Promise((resolve, reject) => {console.log(2);resolve();}).then(function () {console.log('3.我是新增的微任务');})}, 1000);console.log(4);let res = new Promise((resolve, reject) => {console.log(5);resolve();}).then(function () {console.log('6.我是新增的微任务');})console.log(7);setTimeout(function () {console.log(8);console.log(9);let res = new Promise((resolve, reject) => {console.log(10);resolve();}).then(function () {console.log('11.我是新增的微任务');})}, 0);
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210712152133835.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NjE4Nzg4,size_16,color_FFFFFF,t_70
从上述这个案例,js代码运行机制,我个人认为可以把setimeout当做一个 独立模块执行的伪同步任务。可以这么理解,当同步任务执行完后继续执行异步任务中的微任务,当异步中所有微任务执行完毕后,继续执行异步中的宏任务。此时把这个宏任务,理解成一个伪同步任务,就容易理解多了。这个等待运行的过程叫做事件队列,这个执行反复的过程叫做js事件循环。