为什么要使用Promise对象
在没有Promise对象之前,我们是如何处理异步任务的呢。
当一个异步的操作需要另一个异步操作的结果作为参数时,我们应该如何实现呢。
// 第一层
$.ajax({
url: '',
success: (res1) => {
// 第二层
$.ajax({
url: '',
data: res1,
success: (res2) => {
// 第三层
$.ajax({
url: '',
data: res2,
success: (res3) => {
console.log(res3);
}
})
}
})
}
})
如果想获取上一个异步操作的结果作为下一个异步操作的参数,只能将一个异步操作嵌套一个异步操作的实现。
ES6的Promise出现后,我们就可以防止这种一层一层的嵌套了
let promise1 = new Promise(function (resolve, reject) {
$.ajax({
url: '',
success: (res1) => {
resolve(res1)
}
})
})
let promise2 = new Promise(function (resolve, reject) {
$.ajax({
url: '',
success: (res2) => {
resolve(res2)
}
})
})
let promise3 = new Promise(function (resolve, reject) {
$.ajax({
url: '',
success: (res3) => {
resolve(res3)
}
})
})
promise1.then(promise2).then(promise3)
Promise的定义
Promise是一个对象,它可以获取异步操作的信息。Promise提供统一的API,各种异步操作可以用同样的方法处理。
Promise对象有两个特点
1、对象状态不受外界影响
Promise对象有三个状态:
- pending : 进行中
- fulfilled:已成功
- rejected:已失败
只有异步操作返回的结果,才可以决定当前是哪种状态,其他任何操作都无法改变这个状态。
2、状态的变化只有两种可能
- 从
pending变成fulfilled - 从
pending变成rejected
只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。
Promise解决的问题
- 回调地狱,代码难以维护,常常第一个函数的输出是第二个函数的输入
- Promise支持多个并发的请求,获取并发请求中的数据
Promise的缺点
- 无法取消Promise,一旦创建它就会立即执行,中途无法取消
- 如果不设置回调函数,Promise对象内部会抛出错误,可是不会反应到外部
- 当处于pending状态时,无法得知目前进展到哪个状态
Promise的基本使用
Promise构造函数接收一个函数作为参数,这个函数的两个参数分别是resolve和reject,resolve和reject是两个函数,是JavaScript引擎提供的,不用自己部署。
resolve函数的作用是,将Promise对象的状态从pending改为fulfilled,在异步函数操作成功的时候调用,并将异步操作的结果作为参数传递出去。
reject函数的作用是将Promise对象的状态从pedding改为rejected,在异步操作失败的时候调用,并将异步操作报错作为参数传递出去。
创建一个Promise对象,该对象默认会返回两个属性PromiseState、PromiseResult
promise相关API
1、Promise构造函数
new Promise (excutor)
- excutor函数:执行器(resolve,reject)=>{}
- resolve函数:内部定义成功时回调
- reject函数:内部定义失败时回调
说明:excutor函数在promise内部是立即同步执行的
2、Promise.prototype.then方法
Promise.prototype.then = function(onResolved,onRejected){}
- onResolced函数:成功的回调函数
- onRejected函数:失败的回调函数
3、Promise.prototype.catch方法
Promise.prototype.catch = function(onRejected) {}
- onRejected函数:失败的回调函数
4、Promise.resolve方法
Promise.resolve(value)
- value: 可以是简单类型的数据或Promise对象
- 返回值:一个成功/失败的Promise对象
let p = Promise.resolve('asd')
console.log(p); //Promise {<fulfilled>: 'asd'}
let p2 = Promise.resolve(new Promise((resolve,reject)=>{
// resolve('success')
reject('error')
}))
console.log(p2); //Promise {<rejected>: 'error'}
5、Promise.reject方法
Promise.reject(reason)
- reason:可以是简单类型的数据或promise对象
- 返回一个失败的Promise对象
6、Promise.all方法
Promise.all(promises)
- promises: 包含多个promise对象的数组
说明:返回一个新的promise,当所有的promise对象都成功才成功,只要有一个失败就失败
let p1 = new Promise((resolve, reject) => {
resolve('ok')
})
let p2 = Promise.resolve('success')
let p3 = Promise.resolve('成功')
let p4 = Promise.all([p1, p2, p3])
console.log(p4);
所有Promise对象都成功的返回结果
有一个失败的Promise对象就返回该错误的Promise对象
let p1 = new Promise((resolve, reject) => {
reject('error')
})
let p2 = Promise.resolve('success')
let p3 = Promise.resolve('成功')
let p4 = Promise.all([p1, p2, p3])
console.log(p4);

7、Promise.race方法
Proimse.race(promises)
- promises: 包含多个Promise对象
说明:返回一个新的Promise,第一个完成的Promise结果就是最终的结果
Promise的关键问题
1、改变Promise对象的状态方式
- resolve方法:将
pending状态改为fulfilled - reject方法:将
pending状态改为rejected - 抛出异常:通过
throw抛出错误,将pending状态改为rejected
默认情况:Promise的状态为pending
let p = new Promise((resolve,reject)=>{
})
console.log(p);

resolve方法:改变Promise状态
let p = new Promise((resolve,reject)=>{
resolve('ok')
})
console.log(p);

reject方法:改变Promise状态
let p = new Promise((resolve,reject)=>{
reject('error')
})
console.log(p);

2、可以调用多个成功回调
说明:当Promise对象的状态改变的时候,指定的回调都会执行
let p = new Promise((resolve,reject)=>{
resolve('ok')
})
// 回调一
p.then((value)=>{
console.log('1=>',value);
})
// 回调二
p.then((value)=>{
console.log('2=>',value);
})
3、then方法可以链式调用
当then方法使用链式调用时,上一个then方法必须要有返回值。
let p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('ok')
},1000)
})
p.then(value => {
console.log('1');
return value
}).then(value => {
console.log('2');
console.log(value);
})
4、中断then方法链式调用
只有一种方法就是返回值为一个pendind状态的Promise对象
let p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('ok')
},1000)
})
p.then(value => {
console.log('1');
return new Promise(()=>{})
}).then(value => {
console.log('2');
console.log(value);
})
因为一个pending状态的Promise对象是无法调用then方法的
实现Promise对象
// 定义
function Promise(executor) {
// 保存实例对象的this 值
let self = this
// 默认promise状态
this.promiseState = 'pending'
// 默认prmoise结果值
this.promiseResult = undefined
// 保存回调函数 因为可以执行多个回调所以需要用数组存储
this.callback = []
//定义resolve方法
function resolve(data) {
// 限制promise状态只能改变一次
if (self.promiseState !== 'pending') return
// 修改对象状态
self.promiseState = 'fulfilled'
// 设置对象结果
self.promiseResult = data
// 执行异步操作时保存起来的成功回调
self.callback.forEach(item => {
item.onResolved(data)
})
}
// 定义reject方法
function reject(data) {
// 限制promise状态只能改变一次
if (self.promiseState !== 'pending') return
// 修改对象状态
self.promiseState = 'rejected'
// 设置对象结果
self.promiseResult = data
// 执行异步操作时保存起来的成功回调
self.callback.forEach(item => {
item.onRejected(data)
})
}
// 处理抛出的异常需要用trycatch获取
try {
// 同步调用 执行器
executor(resolve, reject)
} catch (e) {
// 调用reject方法
reject(e)
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
let self = this
// 判断回调函数的参数 异常穿透
if (typeof onRejected !== 'function') {
// 创建一个函数
onRejected = reason => {
throw reason
}
}
// 值传递
if (typeof onResolved !== 'function') {
// 创建一个函数
onResolved = value => value
}
// 返回值是一个promise对象
return new Promise((resolve, reject) => {
// 判断promise的状态
if (this.promiseState === 'fulfilled') {
try {
// 获取函数回调的执行结果
let result = onResolved(this.promiseResult)
// 判断返回结果是否为promise对象
if (result instanceof Promise) {
// 如果时 promise对象
result.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
// 结果对象状态为成功
resolve(result)
}
} catch (e) {
reject(e)
}
}
if (this.promiseState === 'rejected') {
try {
// 获取函数回调的执行结果
let result = onRejected(this.promiseResult)
// 判断返回结果是否为promise对象
if (result instanceof Promise) {
// 如果时 promise对象
result.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
// 结果对象状态为成功
resolve(result)
}
} catch (e) {
reject(e)
}
}
// 当执行器里面的代码时异步的时候需要将then的回调函数保存起来
// 当异步操作完成改变状态时在去触发保存起来的回调函数
if (this.promiseState === 'pending') {
this.callback.push({
onResolved: function () {
try {
// 执行成功回调
let result = onResolved(self.promiseResult)
// 判断返回结果是否为promise对象
if (result instanceof Promise) {
// 如果时 promise对象
result.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
// 结果对象状态为成功
resolve(result)
}
} catch (e) {
reject(e)
}
},
onRejected: function () {
try {
// 执行成功回调
let result = onRejected(self.promiseResult)
// 判断返回结果是否为promise对象
if (result instanceof Promise) {
// 如果时 promise对象
result.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
// 结果对象状态为成功
resolve(result)
}
} catch (e) {
reject(e)
}
},
})
}
})
}
// 添加catch放啊
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected)
}
// resolve方法
Promise.resolve = function (value) {
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(value)
}
})
}
// reject方法
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
// all方法
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
let count = 0
let arr = []
// 遍历每个promise对象
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
// 记录成功个数
count++
// 成功的结果保存进数组
arr[i] = v
// 判断是否全部成功
if (count === promises.length) {
resolve(arr)
}
}, r => {
reject(r)
})
}
})
}
// race 方法
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
// 遍历每个promise对象
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
resolve(v)
}, r => {
reject(r)
})
}
})
}