1、Promise
Promise 是 ES6 中一个非常重要和好用的特性,是异步编程的一种解决方案;
通常在网络请求时,我们会处理异步事件,因为不能立即拿到结果,所以往往会传入另外一个函数,在数据请求成功时,将数据通过传入的函数回调出去;
如果只是一个简单的网络请求,那么这种方案不会给我们带来很大的麻烦,但当网络请求非常复杂时,就会出现回调地狱;
2、网络请求的回调地狱
我们来考虑下面的场景:
- 通过一个 url1 从服务器加载一个数据 data1,data1 中包含了下一个请求的 url2
- 再通过 data1 取出 url2,从服务器加载数据 data2,data2 中包含了下一个请求的 url3
- 再通过 data2 取出 url3,从服务器加载数据 data3,data3 中包含了下一个请求的 url4
- 最后发送网络请求 url4,获取最终的数据 data4
正常情况下,上面的代码不会有什么问题,可以正常运行,并且获取我们想要的结果;
但是,这样的代码难看而且不容易维护;
我们期望的是以一种更加优雅的方式来进行这种异步操作:使用 Promise
3、定时器的异步事件
用一个定时器来模拟异步事件:
假设下面的 data 是从网络上 1 秒后请求的数据,console.log
就是我们的处理方式,
这是过去的处理方式,我们将它换成 Promise 代码:
这个例子会让我们感觉使用 Promise 有些多此一举,因为下面的 Promise 代码明显比上面的代码看起来还要复杂;
定时器异步事件解析
我们先来认认真真的读一读这个程序到底做了什么?
new Promise
创建了一个 Promise 对象- 小括号中
((resolve, reject) => {})
是一个箭头函数
- 在创建 Promise 时,传入的这个箭头函数是固定的(一般我们都会这样写)
- resolve 和 reject 也是函数,通常情况下,会根据请求数据的成功和失败来决定调用哪一个
- 如果是成功的,通常会调用
resolve(messsage)
,这时,后续的 then 会被回调 - 如果是失败的,通常会调用
reject(error)
,这时,后续的 catch 会被回调
4、promise 的三种状态
当开发中有异步操作时,可以给异步操作包装一个 Promise,异步操作之后会有三种状态:
- pending:等待状态,比如正在进行网络请求,或者定时器没有到时间
- fulfill:满足状态,当我们主动回调了 resolve 时,就处于该状态,并且会回调
.then()
- reject:拒绝状态,当我们主动回调了 reject 时,就处于该状态,并且会回调
.catch()
以上代码的另一种写法:
5、Primose的链式调用
<script> // promise 链式调用 new Promise((resolve, reject) => { setTimeout(() => { resolve('Hello World') }, 1000) }).then(data => { console.log(data) // Hello World return Promise.resolve(data + '111') }).then(data => { console.log(data) // Hello World111 return Promise.resolve(data + '222') }).then(data => { console.log(data) // Hello World111222 return Promise.reject(data + 'error') }).then(data => { console.log(data) // 这里代码不会执行,没有输出 return Promise.resolve(data + '333') }).catch(data => { console.log(data) // Hello World111222error return Promise.resolve(data + '444') }).then(data => { console.log(data) // Hello World111222error444 }) </script>
链式调用简写
将数据直接包装成 Promise.resolve,在 then 中直接返回:
<script> // promise 链式调用简写 new Promise((resolve, reject) => { setTimeout(() => { resolve('Hello World') }, 1000) }).then(data => { console.log(data) // Hello World return data + '111' }).then(data => { console.log(data) // Hello World111 return data + '222' }).then(data => { console.log(data) // Hello World111222 return Promise.reject(data + 'error') }).then(data => { console.log(data) // 这里代码不会执行,没有输出 return data + '333' }).catch(data => { console.log(data) // Hello World111222error return data + '444' }).then(data => { console.log(data) // Hello World111222error444 }) </script>
6、promise的all方法的使用
<script> // Promise 的 all 方法使用 Promise.all([ new Promise((resolve, reject) => { setTimeout(() => { resolve({ name: 'lyy', age: 18 }) }, 1000) }), new Promise((resolve, reject) => { setTimeout(() => { resolve({ name: 'sss', age: 17 }) }, 2000) }) ]).then(results => { console.log(results); }) </script>