KonishiLee's Blog

Promise 介绍

简介

都知道 JS 语言执行环境是 “single thread”。意思就是一次只能执行一个任务,任务必须排队,如果要执行下一个任务,就必须等到当前的任务执行完。

这种模式相对于来说比较单纯,容易理解。但是如果其中一个任务比较耗时,那剩下的任务就必须排队等待,这样容易出现浏览器无响应(假死)的状态。

为了解决这个问题,JS 的执行模式就被分成了两种:同步(Synchronous)异步(Asynchronous)

同步模式” 就是下一个任务要等到上一个任务执行完成之后才执行,执行的顺序是一致的,同步的。

异步模式” 就是每个任务都有一个或者多个回调函数(callback),上一个任务执行后,不是执行下一个任务,而是先执行回调函数,下一个任务不需要等到上一个任务执行完就开始执行,执行的顺序是不一致的,异步的。

用法

简单的讲述了 Promise,那就来看看怎么样来实现吧。

一段普通的同步方法,执行的顺序是一致的。

1
2
3
for (var i = 0; i < 5; i++) {
console.log(i)
}

执行结果:0,1,2,3,4

这个地方可能看不出来有什么区别,那我们重新来改造一下。

1
2
3
4
5
6
7
for (var i = 0; i < 5; i++) {
((i) => {
setTimeout(function(){
console.log(i)
}, (5 - i) * 1000)
})(i)
}

这个改动可能有点复杂,首先加入了闭包的概念,因为需要更好的看到执行出来的一个顺序,其次加入了 setTimeout,因为这个地方需要制造一个当 i 越小的时候他的函数执行的时间越久,所以输出的结果才会是倒序,这里其实也可以加一个随机数的概念,然后能真正体会到执行顺序的不一致。

执行结果:4,3,2,1,0

理解了异步之后,那我们再来改进一下代码,加入 Promise。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var tasks = [];
var outPrint = (i) => new Promise((resolve) => {
setTimeout(() => {
console.log(i);
resolve();
}, (5 - i) * 1000);
});
for (var i = 0; i < 5; i++) {
tasks.push(outPrint(i));
}
Promise.all(tasks).then(() => {
console.log(5);
});

这一段代码其实如果本身按照顺序的话应该先执行 5 才是,但是正因为加入了 Promise,所以在执行 5 之前必须先要执行 for 循环里的代码。这样就形成了链式调用,让我们更加清晰的管理我们的异步方法。

执行结果是:4,3,2,1,0,5

下面介绍一下 ES7 的写法 asyncawait,是不是感觉更加好用了呢?

1
2
3
4
5
6
7
8
9
10
11
var asyncTask = () => new Promise((resolve) => {
setTimeout(() => {
console.log(2)
resolve()
}, 2000);
});
(async () => {
await asyncTask();
console.log(1);
})();

执行结果是:2,1

如果喜欢这个分享,就帮忙买杯咖啡吧