1. 概念
- 1.Promise是ES6引入的进行异步编程的新的解决方案
注:旧的方案是单纯地使用回调函数 - 2.从语法上说:Promise是一个构造函数,用来生成
Promise实例 - 3.从功能上说:Promise对象用来封装一个异步操作并可以获取其成功或失败的结果值
- 4
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject - (1)
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功” - (2)
reject函数的作用是,将Promise对象的状态从“未完成”变为“失败” 一个Promise必然处于以下几种状态之一:
Promise的状态:实例对象中的一个属性 PromiseState
说明:一个Promise对象只能改变一次 - 待定(pending) : 初始状态,既没有被兑现,也没有被拒绝。
- 已兑现(fulfilled) : 意味着操作成功完成。
- 已拒绝(rejected) : 意味着操作失败。
// promise对象的值
// 实例对象中的另一个属性 PromiseResult
// 保存着异步任务成功或失败的结果
// resolve、reject函数可以对 PromiseResult的值进行修改赋值
const promise = new Promise(function(resolve, reject) {
// 逻辑
// 同步执行 【即 promise对象创建后,立即执行】
if('异步操作成功') {
resolve(value) // 成功的回调
} else {
reject(error) // 失败的回调
}
});
// `Promise`实例生成以后,可以用`then`方法分别指定`resolved`状态和`rejected`状态的回调函数。
// 不管`promise`最后的状态,在执行完`then`或`catch`指定的回调函数以后,都会执行`finally`方法指定的回调函数。
myPromise
.then(
(resolve) => {
},
(reject) => {
}
).catch(error => {
}).finally(() => {
})
2. Promise基本流程
3. promise优点
支持链式调用,可以解决回调地狱问题
- 1.回调地狱:回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件
- 2.回调地狱的缺点:不便于阅读,不便于异常处理
const doSomething = (doIt) => {
// console.log('doIt', doIt)
setTimeout(() => {
console.log('doSomething')
return doIt('doSomething')
}, 500);
}
const doSomethingElse = (result, doIts) => {
setTimeout(() => {
console.log('doSomethingElse', result)
return doIts('doSomethingElse')
}, 500);
}
const doThirdThing = (newResult, doTest) => {
setTimeout(() => {
console.log('doThirdThing', newResult)
return doTest('finally')
}, 500);
}
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('得到最终结果: ' + finalResult);
});
});
});
// 输出:doSomething
// doSomethingElse doSomething
// doThirdThing doSomethingElse
// 得到最终结果: finally
// 上述代码就是典型的异步回调。
// 通过`Promise`的改写上面的代码
const doSomething = new Promise((resolve) => {
resolve('doSomething')
})
const doSomethingElse = (result) => {
return new Promise((resolve, reject) =>
{
setTimeout(() => {
resolve('doSomethingElse')
console.log('doSomethingElse', result)
}, 500);
})
}
const doThirdThing = (newResult) => {
return new Promise((resolve, reject)=> {
setTimeout(() => {
resolve('doThirdThing')
console.log('doThirdThing', newResult)
}, 500);
})
}
const failureCallback = new Promise((resolve, reject) => {
return setTimeout(() => {
resolve()
console.log('failureCallback')
}, 500)
})
doSomething.then(function(result) {
return doSomethingElse(result);
})
.then(function(newResult) {
return doThirdThing(newResult);
})
.then(function(finalResult) {
console.log('得到最终结果: ' + finalResult);
})
// 打印输出:
// failureCallback
// doSomethingElse doSomething
// doThirdThing doSomethingElse
// 得到最终结果: doThirdThing
// promise解决异步操作的优点
// - 链式操作减低了编码难度
// - 代码可读性明显增强
4. Promise构建出来的实例存在以下方法:(实例方法)
- then()
- catch()
- finally()
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
5. 构造函数方法
- all()
- race()
- allSettled()
- resolve()
- reject()
// `Promise.all()`方法用于将多个 `Promise`实例,包装成一个新的 `Promise`实例
// 接受一个数组(迭代对象)作为参数,数组成员都应为`Promise`实例
const p = Promise.all([p1, p2, p3]);
// 实例`p`的状态由`p1`、`p2`、`p3`决定,分为两种:
// - 只有`p1`、`p2`、`p3`的状态都变成`fulfilled`,`p`的状态才会变成`fulfilled`,此时`p1`、`p2`、`p3`的返回值组成一个数组,传递给`p`的回调函数
// - 只要`p1`、`p2`、`p3`之中有一个被`rejected`,`p`的状态就变成`rejected`,此时第一个被`reject`的实例的返回值,会传递给`p`的回调函数
const e1 = new Promise((resolve, reject) => {
resolve('e1')
})
const e2 = new Promise((resolve, reject) => {
resolve('e2')
})
const e3 = new Promise((resolve, reject) => {
resolve('e3')
})
const p4 = Promise.all([e1, e2, e3])
console.log(p4)
// 控制台输出:
Promise {<pending>}
[[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: Array(3)
const e1 = new Promise((resolve, reject) => {
resolve('e1')
})
const e2 = new Promise((resolve, reject) => {
reject('e2')
})
const e3 = new Promise((resolve, reject) => {
reject('e3')
})
const p4 = Promise.all([e1, e2, e3])
console.log(p4)
// 控制台输出:
Promise {<pending>}
[[Prototype]]: Promise
[[PromiseState]]: "rejected"
[[PromiseResult]]: "e2"
// `Promise.race()`方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例
const p = Promise.race([p1, p2, p3]);
// 只要`p1`、`p2`、`p3`之中有一个实例率先改变状态,`p`的状态就跟着改变
// 率先改变的 Promise 实例的返回值则传递给`p`的回调函数
const p = Promise.race([
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout...')), 500)
}),
new Promise(function (resolve, reject) {
setTimeout(() => resolve('ok'), 500)
})
]);
p
.then(console.log)
.catch(console.error);
// 控制台输出: Error: request timeout...
// allSettled()
// `Promise.allSettled()`方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例
// 只有等到所有这些参数实例都返回结果,不管是`fulfilled`还是`rejected`,包装实例才会结束
// resolve方法是函数对象的方法,并不是实例对象的方法(then,catch,finally)
// 接受一个参数,并返回一个成功、失败的promise对象
const p1 = Promise.resolve('todo')
// (1) resolve方法中传入的参数为 非promise类型的对象时,则返回的结果为成功Promise对象
console.log(p1)
// (2) resolve方法中传入的参数为p romise类型的对象时,参数的结果决定了 resolve 的结果
const p2 = Promise.resolve(new Promise((resolve, reject) => {
// resolve('ok')
reject('error')
}))
console.log(p2)
p2.catch(reason => {
console.log(reason)
})
// reject 方法
// 接受一个参数,并返回一个新的 Promise 实例,该实例的状态为rejected
const p3 = Promise.reject('出错了')
// 等同于
// const p3 = new Promise((resolve, reject)=> {
// reject('出错了')
// })
console.log(p3)
p3.catch(reason => {
console.log(reason)
})