(What)什么是Promise?
-
Promise是异步编程的新的解决方案,比起旧的解决方案(回调)更合理更强大。
- 从语法上来说:Promise是一个构造函数
- 从功能上来说:Promise对象用来封装一个异步操作并可以获取其结果
-
Promise的状态改变
- 调用resolve函数来将promise当前状态pending(进行中)改成fulfilled(已成功)
- 调用reject函数来将promise当前状态pending(进行中)改成rejected(已失败)
说明:只有这2种状态的改变,且promise对象只能改变一次,无论变为成功还是失败,都会有一个结果数据,成功的结果数据一般称为value,失败的结果数据一般称为reason。
- Promise的基本流程
- Promise的基本使用
根据上述Promise的基本流程实现一个Promise的基本使用。
定义一个全局的常量,该常量为[1,10]之间的随机整数。若该常量为偶数,Promise状态为fulfilled,调用 resolve(value);若该常量为奇数,Promise状态为rejected,调用reject(reason)。
const num = Math.floor(Math.random() * 10 + 1)
const p = new Promise((resolve, reject) => {
setTimeout(() => {
if (num % 2 == 0) {
resolve('fulfilled状态')
} else {
reject('rejected状态')
}
}, 1000);
})
p.then(
value => {
console.log('onFulfillment,num is ' + num)
},
reason => {
console.log('onRejection,num is ' + num)
}
)
(Why)为什么要用Promise?
- 指定回调函数的方式更加灵活(旧的解决方案必须在启动异步任务前指定回调函数)
- 支持链式调用,可以解决回调地狱问题
- 回调地狱
- 什么是回调地狱?什么时候会使用回调地狱?回调地狱的缺点?
- 回调地狱
//回调地狱
doSomenthing(function (result) {
doSecondThing(result, function (secondResult) {
doThirdThing(newResult, function (thirdResult) {
console.log(thirdResult);
}, failureCallback)
}, failureCallback)
}, failureCallback)
以上代码简单的描述了回调地狱。在多个串联的异步操作会出现回调地狱。回调地狱的缺点:以前一个异步任务的结果为条件;回调函数嵌套使得代码难以阅读;异常处理分别输出。
- 使用Promise解决回调地狱
doSomenthing()
.then(function (result) {
return doSecondthing(result)
})
.then(function (secondResult) {
return doThirdthing(secondResult)
})
.then(function (thirdResult) {
console.log(thirdResult);
})
.catch(failureCallback)
- 使用async/await解决回调地狱
async function request() {
try {
const result = await doSomething()
const secondResult = await doSecondthing()
const thirdResult = await doThirdthing()
console.log(thirdResult);
} catch (error) {
failureCallback
}
}
(How)如何使用Promise?
- Promise构造函数:executor
new Promise((resolve, reject) => {...} /* executor */ );
Promise构造函数执行时立即调用executor 函数,分别将promise的状态改为fulfilled(完成)或rejected(失败)。
- Promise.prototype.then()
p.then(onFulfilled[, onRejected]);
p.then(value => {
// fulfillment
}, reason => {
// rejection
});
内部定义成功时的回调函数(value)=>{},内部定义失败时的回调函数(reason)=>{}。
- Promise.prototype.catch()
p.catch(onRejected);
p.catch(function (reason) {
// 拒绝
});
失败时的回调函数(reason)=>{},then()的语法糖,相当于then(undefined, onRejected)
- Promise.resolve()
const testResolve = Promise.resolve('返回一个以给定值解析后的Promise 对象');
testResolve.then((value) => {
console.log(value);
// expected output: 返回一个以给定值解析后的Promise 对象
});
- Promise.reject()
const testReject = Promise.reject('返回一个失败的对象');
//reason:失败原因
testReject.then((reason) => {
console.log(reason);
// expected output: 返回一个失败的对象
});
结合上述五个写一个简单的例子
const testPromise = new Promise((resolve, reject) => {
//executor函数
setTimeout(() => {
// resolve('我是成功数据')
reject('我是失败数据')
}, 1000);
}).then(
value => {
console.log(value)
}
).catch(
reason => {
console.log(reason)
}
)
- Promise.all()
const p1 = Promise.resolve(1)
const p2 = Promise.resolve(2)
const p3 = Promise.reject(3)
const p4 = Promise.reject(4)
const pAll = Promise.all([p2, p1]) //[p1,p2,p4,p3]
pAll.then(
values => {
console.log('我们是成功数据' + values);
}
).catch(
reason => {
console.log('我是失败数据' + reason);
}
)
如果所有参数都成功(resolved),此实例回调成功(resolve),按调用all的参数顺序输出。
此时输出的结果为:我们是成功数据2,1。
如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。若将参数[p2, p1]换成[p1,p2,p4,p3]。
此时输出的结果为:我是失败数据4。
- Promise.race()
const p1 = Promise.resolve(1)
const p2 = Promise.resolve(2)
const p3 = Promise.reject(3)
const p4 = Promise.reject(4)
const pRace = Promise.race([p2, p1])
pRace.then(
values => {
console.log('我们是成功数据' + values);
}
).catch(
reason => {
console.log('我是失败数据' + reason);
}
)
第一个完成的promise的结果状态就是最终的结果状态