一、什么是promise
Promise是一种异步编程的解决方案,用于处理异步操作并返回结果,从语法上看它是一个构造函数,从功能上看它是用来封装一个异步操作并可以获取它成功/失败的结果值。
1.概念
简单来说就是一个容器,里面保存着未来才会结束的事件( 通常是一个异步操作 )的结果。从语法上来说,Promise
是个对象,从它可以获取异步操作的消息。Promise
提供统一的 API
,各种异步操作(定时器、ajax请求等)都可以用同样的方法进行处理。
2.特点
1、promise有三种状态 进行中(pending)、已成功(fulfilled)、已失败(rejected)、且promise必然处在这三种状态之中
2、一旦状态改变,就不会再改变,任何时候都可以得到这个结果。状态改变只有两种状态从pending变为fulfilled和从pending变为rejected。
二、用法
1.基本用法
// Promise构造函数接受一个函数(执行器函数)作为参数,
// 该函数的两个参数分别是resolve和reject。它们是两个函数,
// 由 JavaScript 引擎提供,不用自己部署。
const promise = new Promise(function (resolve, reject) {
// ... some code
if (/* 异步操作成功 */) {
// 在异步操作成功时调用,并将异步操作的结果,作为参数value传递出去;
resolve(value);
} else {
// 在异步操作失败时调用,并将异步操作报出的错误,作为参数error/reason传递出去。
reject(error);
}
});
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。
promise.then(function(value) {
// success
}, function(error) {
// failure
});
then
方法可以接受两个回调函数作为参数。
- 第一个回调函数是
Promise
对象的状态变为resolved
时调用。 - 第二个回调函数是
Promise
对象的状态变为rejected
时调用。
// 创建一个新的p对象promise
const p = new Promise((resolve, reject) => { // 执行器函数
// 执行异步操作任务
setTimeout(() => {
const time = Date.now()
// 如果当前时间是偶数代表成功,否则失败
if (time % 2 == 0) {
// 如果成功,调用resolve(value)
resolve('成功的数据,time=' + time)
} else {
// 如果失败,调用reject(reason)
reject('失败的数据,time=' + time)
}
}, 1000);
})
p.then(
value => { // 接收得到成功的value数据 onResolved
console.log('成功的回调', value) // 成功的回调 成功的数据
},
reason => { // 接收得到失败的reason数据 onRejected
console.log('失败的回调', reason) // 失败的回调 失败的数据
}
)
2.Promise.prototype.then 方法
(onResolved, onRejected) => {} 指定两个回调(成功+失败)
onResolved 是成功的回调函数,onRejected是失败的回调函数
3.Promise.prototype.catch 方法
onRejected 函数: 失败的回调函数 (reason) => {}
catch是then的语法糖,相当于then(undefined, onRejected)
4.Promise.resolve方法 Promise.resolve(value) => {}
let p1 = Promise.resolve(521);
console.log(p1); // Promise {<fulfilled>: 521}
返回一个成功/失败的 promise
对象
value:传入一个promise或者成功的数据
如果传入的参数为 Promise
对象, 则参数的结果决定了 resolve
的结果
let p2 = Promise.resolve(new Promise((resolve, reject) => {
// resolve('OK'); // 成功的Promise
reject('Error');
}));
console.log(p2);
p2.catch(reason => {
console.log(reason);
})
5.Promise.reject 方法: Promise.resolve(reason) => {}
返回一个失败的 promise 对象
let p = Promise.reject(521);
let p2 = Promise.reject('iloveyou');
let p3 = Promise.reject(new Promise((resolve, reject) => {
resolve('OK');
}));
console.log(p);
console.log(p2);
console.log(p3);
Promise.resolve() / Promise.reject() 方法就是一个语法糖,用来快速得到Promise对象
6. Promise.all 方法: Promise.all(iterable) => {}
iterable
:包含 n 个promise
的可迭代对象,如Array
或String
- 返回一个新的
promise
,只有所有的promise
都成功才成功,只要有一个失败了就直接失败。
let p1 = new Promise((resolve, reject) => {
resolve('OK');
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');
const result = Promise.all([p1, p2, p3]);
console.log(result);
result.then(res => {
console.log(res, '打印结果');
})
且用then回调函数参数也为数组
let p1 = new Promise((resolve, reject) => {
resolve('OK');
})
let p2 = Promise.reject('Error');
let p3 = Promise.resolve('Oh Yeah');
const result = Promise.all([p1, p2, p3]);
console.log(result);
result.then(res => {
console.log(res);
}).catch(msg => {
console.log(msg);
})
当有一个不成功时就会失败
Promise.all( ).then( )适用于处理多个异步任务,且所有的异步任务都得到结果时的情况。
使用场景:用户点击按钮,会弹出一个弹出对话框,对话框中有两部分数据呈现,这两部分数据分别是不同的后端接口获取的数据。弹框弹出后的初始情况下,就让这个弹出框处于数据加载中
的状态,当这两部分数据都从接口获取到的时候,才让这个数据加载中
状态消失。让用户看到这两部分的数据。
7. Promise.race方法:Promise.race(iterableiterableiterableiterableiterableiterableiterable) => {}
iterable
:包含 n 个promise
的可迭代对象,如Array
或String
- 返回一个新的
promise
, 第一个完成的promise
的结果状态就是最终的结果状态。
// 谁先完成就输出谁(不管是成功还是失败)
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000)
})
const p2 = Promise.resolve(2)
const p3 = Promise.reject(3)
const pRace = Promise.race([p1, p2, p3])
pRace.then(
value => {
console.log('race onResolved()', value)
},
reason => {
console.log('race onRejected()', reason)
}
)
类似于Promise.all() ,区别在于 它有任意一个返回成功后,就算完成,但是 进程不会立即停止
使用场景:把异步操作和定时器放到一起,如果定时器先触发,认为超时,告知用户
8.promise关键点
如何改变promise的状态:通过resolve(value)、reject(reason)、 抛出异常 可以改变promise的状态
const p = new Promise((resolve, reject) => {
//resolve(1) // promise变为resolved成功状态
//reject(2) // promise变为rejected失败状态
throw new Error('出错了') // 抛出异常,promise变为rejected失败状态,reason为抛出的error
})
p.then(
value => { },
reason => { console.log('reason', reason) }
)
9.promise链式调用
promise
的 then()
返回一个新的 promise
, 可以开写成 then()
的链式调用
new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行任务1(异步)')
resolve(1)
}, 1000)
}).then(
value => {
console.log('任务1的结果', value)
console.log('执行任务2(同步)')
return 2 // 同步任务直接return返回结果
}
).then(
value => {
console.log('任务2的结果', value)
return new Promise((resolve, reject) => { // 异步任务需要包裹在Promise对象中
setTimeout(() => {
console.log('执行任务3(异步)')
resolve(3)
}, 1000)
})
}
).then(
value => {
console.log('任务3的结果', value)
}
)
链式调用的原理:
因为then方法也会返回一个新的Promise, 然后这个Promise会根据它接收的参数,来决定状态, 如果接收到的不是一个Promise, 那么它就自动置为fullfill, 如果接收到的参数是Promise, 那么就将它的resolve函数放在接收到的Promise中的then方法执行, 所以就保证了只有接收到的参数的那个Promise执行完, 返回的的Promise才会执行,也就形成链式调用的过程