1.基本概念
promise是对异步编程的一种抽象。它是一个代理对象,代表一个必须进行异步处理的函数返回的值或抛出的异常。也就是说promise对象代表了一个异步操作,可以将异步对象和回调函数脱离开来,通过then方法在这个异步操作上面绑定回调函数。
状态
promise有3种状态:pending(待解决,这也是初始化状态),fulfilled(完成),rejected(拒绝)。
接口
promise唯一接口then方法,它需要2个参数,分别是resolve和rejectedr。并且返回一个promise对象来支持链式调用。
2.Promise的创建
Promise创建时,会传给promise一个称为excutor
执行器的函数。这个excutor
我们可以理解为生产者的生产过程函数。这个函数含有两个参数resolve
和reject
,这俩参数也同样是函数,用来传递异步操作的结果。
let promise = new Promise(function(resolve, reject) {
// executor
})
- 在promise对象创建时,
excutor
会立即执行。 - 在
resolve
和reject
是JS引擎自动创建的函数,我们无需自己创建,只需将其作为参数传入就好。 - 创建的
promise
的内部状态是个对象,初始时为:
{
state, //pending
result, //undefined
}
Promise的then,catch和finally
在上面例子中,既然生产者的行为完成了,结果也传递出去了,那么如何通知消费者呢?我们可以使用.then
, .catch
, 和.finally
来注册消费者的函数,把.then
,.catch
,.finally
看做是个订阅列表,将消费者的函数注册于此,一旦收到结果时,就可以通知到对方进行相应的处理。
.then
//.then
promise.then(
result = > resultHandle(result)
error = > errorHandle(error)
)
.then()
接收2个函数,一个用来处理正常结果result
,一个用来处理error
,但一般情况下,我们也可以不用在.then()
中传入这个error
处理的函数。
.catch
promise.catch(
error = > errorHandle(error)
)
其实这就是相当于promise.then(null, errorHandle)
。 .catch
会捕获到整个异步操作中,或者是一系列连续的异步操作链中的出现的任何类型的错误,一旦抛出错误,则会直接转入到.catch
中进行错误处理。
.finally
promise.finally(
finalHandle
)
当promise的状态确定时,即无论拿到的是正常结果还是错误信息,总会执行这个finalHandle
函数。用.finally
可以做一些清理操作,比如发起网络请求后,可以停止loading显示。
3.Promise链式调用
当有一系列的异步操作需要一个接一个执行时,可以使用promise的调用链。 举个例子,我们用fetch
这个方法去发起网络请求,fetch()
返回的是一个promise对象,那么我们可以对其连续地调用.then
来进行一步步连续地异步操作。注意:promise.then()
返回的是一个新的promise对象,所以我们才可以继续对其调用.then
。
// Make a request for user.json
fetch('/article/promise-chaining/user.json')
// Load it as json
.then(response => response.json())
// Make a request to github
.then(user => fetch(`https://api.github.com/users/${user.name}`))
// Load the response as json
.then(response => response.json())
// Show the avatar image (githubUser.avatar_url) for 3 seconds (maybe animate it)
.then(githubUser => {
let img = document.createElement('img');
img.src = githubUser.avatar_url;
img.className = "promise-avatar-example";
document.body.append(img);
setTimeout(() => img.remove(), 3000); // (*)
}).catch(error => console.log(error));
这段代码的作用就是先发起网络请求获取到服务端的相应内容(其实只是响应头),然后通过调用response.json()
继续获取response
完整的远程数据并将其解析为JSON格式(也是异步操作),接着根据json中user的name信息,继续发起网络请求,拿到用户object及其头像url,展示其头像并在3秒后删除头像图片。.catch
会处理上面一系列流程中出现的任何错误。