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事件循环。