异步经常用到Promise,所以复习下,往后有疑问再看。
Promise 对象用于表示一个异步操作的最终状态(完成或失败),以及该异步操作的结果值。
官网注解不配合代码,理解起来有点难度,接下来仔细的解析一遍,说清楚为止。
我们熟悉的场景
var promise = new Promise(function(resolve,reject){
$.ajax({
url:'/api/poisearch.json',
method:'get',
datatype:'json',
success:(res) =>{
resolve(res)
},
error:(err)=>{
reject(err)
}
})
})
promise.then(res => res.data)
.then(data => data.result)
.then(result => console.log(result));
Promise语法
Promise是异步里面的一种解决方案,解决了回调嵌套的问题,es6将其进行了语言标准,同意了用法,提供了promise
对象, promise对象有三种状态:pending(进行中) 、Resolved(已经完成)和Rejected(已失败)
ES6规定,Promise对象是一个构造函数,用来生成Promise实例
var promise=new Promise(function(resove,reject){
//executor
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
})
Promise实例生成以后,可以用then方法分别指定Resolved状态和Reject状态的回调函数。
promise.then(function(value) {
// success
}, function(error) {
// failure
});
executor 是resolve 和 reject 两个参数的函数 。Promise构造函数执行时立即调用executor 函数, resolve 和 reject 两个函数作为参数传递给executor(executor 函数在Promise构造函数返回所建promise实例对象前被调用)。resolve 和 reject 函数被调用时,分别将promise的状态改为Resolved(完成)或rejected(失败)。executor 内部通常会执行一些异步操作,一旦异步操作执行完毕(可能成功/失败),要么调用resolve函数来将promise状态改成fulfilled,要么调用reject 函数将promise的状态改为rejected。如果在executor函数中抛出一个错误,那么该promise 状态为rejected。executor函数的返回值被忽略。
Promise 对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。
一个 Promise有以下几种状态:
pending: 初始状态,既不是成功,也不是失败状态。
resolved: 意味着操作成功完成。
rejected: 意味着操作失败
pending 状态的 Promise 对象可能会变为Resolved状态并传递一个值给相应的状态处理方法,也可能变为失败状态(rejected)并传递失败信息。当其中任一种情况出现时,Promise 对象的 then
方法绑定的处理方法(handlers )就会被调用(then方法包含两个参数:onresolved 和 onrejected,它们都是 Function 类型。当Promise状态为Resolved时,调用 then 的 onresolved 方法,当Promise状态为rejected时,调用 then 的 onrejected 方法, 所以在异步操作的完成和绑定处理方法之间不存在竞争)。
官方例子
- 简单例子
let myFirstPromise = new Promise(function(resolve, reject){
//当异步代码执行成功时,我们才会调用resolve(...), 当异步代码失败时就会调用reject(...)
//在本例中,我们使用setTimeout(...)来模拟异步代码,实际编码时可能是XHR请求或是HTML5的一些API方法.
setTimeout(function(){
resolve("成功!"); //代码正常执行!
}, 250);
});
myFirstPromise.then(function(successMessage){
//successMessage的值是上面调用resolve(...)方法传入的值.
//successMessage参数不一定非要是字符串类型,这里只是举个例子
console.log("Yay! " + successMessage);
});
- 高级点的例子
'use strict';
var promiseCount = 0;
function testPromise() {
let thisPromiseCount = ++promiseCount;
let log = document.getElementById('log');
log.insertAdjacentHTML('beforeend', thisPromiseCount +
') 开始 (同步代码开始)
');
// 新构建一个 Promise 实例:使用Promise实现每过一段时间给计数器加一的过程,每段时间间隔为1~3秒不等
let p1 = new Promise(
// resolver 函数在 Promise 成功或失败时都可能被调用
(resolve, reject) => {
log.insertAdjacentHTML('beforeend', thisPromiseCount +
') Promise 开始 (异步代码开始)
');
// 创建一个异步调用
window.setTimeout(
function() {
// 填充 Promise
resolve(thisPromiseCount);
}, Math.random() * 2000 + 1000);
}
);
// Promise 不论成功或失败都会调用 then
// catch() 只有当 promise 失败时才会调用
p1.then(
// 记录填充值
function(val) {
log.insertAdjacentHTML('beforeend', val +
') Promise 已填充完毕 (异步代码结束)
');
})
.catch(
// 记录失败原因
(reason) => {
console.log('处理失败的 promise ('+reason+')');
});
log.insertAdjacentHTML('beforeend', thisPromiseCount +
') Promise made (同步代码结束)
');
}
本例展示了 Promise
的一些机制。 testPromise()
方法在每次点击 按钮时被调用,该方法会创建一个promise 对象,使用
window.setTimeout()
让Promise等待 1-3 秒不等的时间来填充数据(通过Math.random()方法)。
Promise 的值的填充过程都被日志记录(logged)下来,这些日志信息展示了方法中的同步代码和异步代码是如何通过Promise完成解耦的。
测试结果:
- 开始 (同步代码开始)
- Promise 开始 (异步代码开始)
- Promise made (同步代码结束)
- Promise 已填充完毕 (异步代码结束)