Promise 使用整理
说明
Promise 就是一个对象,用来传递异步操作的信息,他代表某个未来才会知道结果的操作。有了 Promise 就可以将异步操作以同步操作的流程表达出来,避免层层嵌套回调函数
特点
对象的状态不受外界影响,Promise 对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成)、Rejected(已失败),只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法更改这个状态
一旦状态改变就不会再变化 只能从 Pending 到 Resolved 或者从 Pending 到 Rejected,状态发生后就会一直保持这个结果
1. 创建 Promise 实例
const getJSON = function (url) {
const promise = new Promise(function (resolve, reject) {
/*
resolve, reject 由 javascript 引擎提供
resolve:将 Pending(进行中)状态改为 Resolved(已完成)也就是成功时执行,参数可以传递给下一阶段
reject:将 Pending(进行中)状态改为 Rejected(已失败) 也就是失败时执行,参数同样可以传递下去
*/
// 创建请求对象
const xhr = new XMLHttpRequest();
// 建立与服务器链接
xhr.open('GET', url);
// 发送请求
xhr.send();
// 接受服务器响应
xhr.onreadystatechange = function () {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
}
});
return promise;
}
/*
.then() 方法可以接受两个参数,
第一个参数是一个函数,对应 resolve,当状态为 Resolved 时调用,
第二个参数也是函数,对应 reject ,当状态为 Rejected 时调用,但是一般省略这个参数,错误信息放在 .catch 方法中进行
*/
getJSON('../libs/a.json').then(function (json) {
console.log(json);
}, function (error) {
console.error(error);
})
2. Promise.prototype.then()
为 Promise 实例添加状态改变后的回调,then() 方法 返回的是一个新的 Promise 实例,可以采用链式语法,指定一组回调函数的执行次序
getJSON('../libs/a.json').then(function (json) {
return JSON.parse(json);
}).then(function (json) {
console.log(json);
})
3. Promise.prototype.catch()
用于指定发生错误时的回调,可以捕获错误,
catch() 方法返回的还是一个 Promise 对象,后边可以继续链接 .then() 如果在 catch 之前没有报错,则直接跳过 catch 方法
getJSON('../libs/a.json').then(function (json) {
return JSON.parse(json);
}).then(function (json) {
console.log(json);
}).catch(function (error) {
console.log(error)
})
4. Promise.all([])
用于将多个 Promise 实例包装成一个新的 Promise 实例
- 参数数组中的元素都需要是 Promise 实例,如果不是,会自动转换成 Promise 实例
- 只有数组中的 Promise 实例状态都变为‘已完成’ Promise.all() 的状态才会是 ‘已完成’
- 如果数组中的 Promise 有任何一个的 状态变为 ‘已失败’,Promise.all() 的状态都会变为 ‘已失败’
const promise = Promise.all([
getJSON('../libs/a.json').then(res => JSON.parse(res)),
getJSON('../libs/b.json').then(res => JSON.parse(res)),
['aa', 'bb','cc']
])
promise.then(function (res) {
console.log(res);
/*
[
{"name": "a.json"},
{"name": "b.json"},
['aa', 'bb','cc']
]
*/
}).catch(function (error) {
console.log(error)
})
5. Promise.race([])
与 Promise.all() 方法一样,都是包装一组 Promise 实例为一个新的 Promise 实例
- 参数数组中只要有一个 实例的状态改变,Promise.race 的状态就会改变成相应的状态
const promise = Promise.race([
getJSON('../libs/a.json').then(res => JSON.parse(res)),
getJSON('../libs/b.json').then(res => JSON.parse(res)),
['aa', 'bb','cc']
])
promise.then(function (res) {
console.log(res);
/*
["aa", "bb", "cc"]
*/
}).catch(function (error) {
console.log(error)
})
可以用这个方法设定请求的延迟时间
const timeout = function () {
return new Promise(function (resolve, reject) {
setTimeout(function() {
reject('timeout');
}, 5000);
})
}
const promise = Promise.race([
getJSON('../libs/a.json').then(res => JSON.parse(res)),
timeout()
])
promise.then(function (res) {
console.log(res);
/*
请求超时 5000 毫秒 就报错
*/
}).catch(function (error) {
console.log('wrong')
console.log(error)
})
6. Promise.resolve()
用来将普通对象转换成 Promise 对象
- 参数是 Promise 实例 – 不做修改,直接返回这个实例
- 参数是一个具有 then 方法的对象()– 将这个对象转化成 Promise 对象,并立即执行 then 方法
- 参数是普通的对象,或者不是对象类型的数据 – 返回一个状态为 Resolved 的 Promise 对象(包含数据)
- 不带任何参数 – 返回一个状态为 Resolved 的 Promise 对象(空的)
// 1. 参数是 Promise 实例
const a = new Promise(function (resolve) {
resolve('a');
})
const wrapA = Promise.resolve(a);
wrapA.then(function (res) {
console.log(res); // a
})
console.log(wrapA === a); // true
// 2. 参数是一个具有 then 方法的对象()
const b = {
then: function (resolve) {
resolve('b')
}
}
const wrapB = Promise.resolve(b);
wrapB.then(res => {
console.log(res); // b
})
// 3. 参数是普通的对象,或者不是对象类型的数据
const wrapC = Promise.resolve(['12']);
wrapC.then(res => {
console.log(res); // ['12']
})
// 4. 不带任何参数
const wrapD = Promise.resolve();
wrapD.then((res) => {
console.log(res); // undefined
})
7. Promise.reject()
返回一个新的 Promise 实例,该实例的状态为 rejected
const a = Promise.reject('wrong');
a.then(res => console.log('in then', res))
.catch(res => console.log('in catch', res)) // in catch wrong
特性
Promise 对象表示未来某个将要发生的事件,但在通过 new 创建的时候,作为参数传入的函数是会被立即执行的
then 方法是异步的
const promise = new Promise(function (resolve, reject) {
console.log('in Promise constructor');
resolve('xxx');
console.log('after resolve');
})
console.log('in global');
promise.then(res => {
console.log('in then method', res);
})
console.log('after then method');
/*
// 1. in Promise constructor
// 作为参数传入的函数会被立即执行
// 2. after resolve
// resolve 方法不会中断函数运行
// 3. in global
// 4. after then method
// 5. in then method xxx
// Promise 对象的 then 方法是异步的,所以先打印出 ‘after then method’
*/