Promise是什么
Promise是异步编程的一种解决方案。
具体表达:
语法上来说,Promise是一个构造函数
功能上来说,Promsie对象用来封装一个异步操作并获取其结果
为什么要用Promise
- 指定回调函数的方式更加灵活
回调函数:必须在启动异步任务前指定
Promise: 启动异步任务,返回Promise对象,给Promise对象绑定回调函数(可以在异步任务结束后执行) - 支持链式调用,解决回调地狱问题。
回调地狱:不便于阅读,不便于异常处理
终极解决方案:async...await(完全没有回调函数)
Promise的常用方法
Promise(excutor) // 构造函数
Promise.prototype.then(onResolved, onRejected)
Promise.prototype.catch(onRejected)
Promise.resolve(value)
Promise.reject(reason)
Promise.all(promises)
Promise.race(promises)
Promise的几个关键问题
- 抛出异常,pending会变成rejected
- 一个Promise指定多个成功、失败的回调,都会调用
- Promise.then()返回的Promise对象的结果由什么决定?
1> 简单表达,由then()指定的回调函数执行结果决定
2> 详细表达
a. 如果抛出异常,新Promise变为rejected,reason为抛出的异常
b. 如果返回的是非Promise的任意值,新Promise变为resolved,value为返回值。
c. 如果返回的是另一个新Promise,此Promise的结果就会成为新Promise的结果。 - 如何中断Promise链?
返回一个pending状态的Promise对象 - Promise异常传透?
1> 使用then链式调用的时候,可以在最后指定失败的回调
2> 前面任何操作出了异常,都会传到最后失败的回调处理。
自定义Promise实现
/**
* 自定义Promise
*/
(function(window) {
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
/**
* 构造函数
* @param {function} excutor 执行器函数,有两个函数类型的参数:resolved, rejected
*/
function Promise(excutor) {
const self = this
self.status = PENDING
self.data = undefined // 用来保存Promise的结果
self.callbacks = [] // 用来保存回调函数对象数组,每一项的结构为{ onResolved, onRejected }
function resolve(value) {
if (self.status !== PENDING) { // Promise只能执行一次
return
}
self.status = RESOLVED
self.data = value
if (self.callbacks.length > 0) { // 如果回调函数对象数组不为空,则异步执行每一项的onResolved方法
setTimeout(() => {
self.callbacks.forEach(callbackObj => {
callbackObj.onResolved(value)
})
})
}
}
function reject(reason) {
if (self.status !== PENDING) {
return
}
self.status = REJECTED
self.data = reason
if (self.callbacks.length > 0) {
setTimeout(() => {
self.callbacks.forEach(callbackObj => {
callbackObj.onRejected(reason)
})
})
}
}
try {
excutor(resolve, reject) // 一旦创建,立即执行
} catch (err) { // 如果出现异常,则将该异常作为失败的结果
reject(err)
}
}
/**
* then()方法,返回一个新Promise, 新Promise的执行结果取决于上一个Promise的返回值
* 1. 如果抛出异常,新Promise的执行结果rejected, reason为抛出的异常
* 2. 如果返回值是Promise, 新Promise的执行结果为上一个Promise的执行结果
* 3. 如果返回值是非Promise, 新Promise的执行结果resolved, value为返回值
* @param {function} onResolved Promise执行成功的回调,异步回调,接收一个参数value(Promise执行成功的结果)
* @param {function} onRejected Promise执行失败的回调,异步回调,接收一个参数reason(Promise执行失败的结果)
*/
Promise.prototype.then = function(onResolved, onRejected) {
onResolved = typeof onResolved === 'function' ? onResolved : value => value
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
const self = this
return new Promise((resolve, reject) => {
function handle(callback) {
try {
let result = callback(self.data)
if (result instanceof Promise) {
result.then(resolve, reject)
} else {
resolve(result)
}
} catch (err) {
reject(err)
}
}
if (self.status === RESOLVED) {
setTimeout(() => {
handle(onResolved)
})
} else if (self.status === REJECTED) {
setTimeout(() => {
handle(onRejected)
})
} else if (self.status === PENDING) {
self.callbacks.push({
onResolved: () => handle(onResolved),
onRejected: () => handle(onRejected)
})
}
})
}
/**
* catch()方法,返回一个Promise
* @param {function} onRejected Promise执行失败的回调,异步回调,接收一个参数reason(Promise执行失败的结果)
*/
Promise.prototype.catch = function(onRejected) {
return Promise.then(undefined, onRejected)
}
/**
* resolve()方法,返回一个Promise
* 1. 若value为Promise, 则返回Promise的执行结果为value的执行结果
* 2. 若value为非Promise, 则返回一个执行结果为value的成功Promise
* @param {any} value
*/
Promise.resolve = function(value) {
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(resolve, reject)
} else {
resolve(value)
}
})
}
/**
* reject()方法,返回一个指定结果为reason的失败的Promise
* @param {any} reason
*/
Promise.reject = function(reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
/**
* 返回一个Promise
* 1. 有一个失败,结果为失败的结果
* 2. 都成功,结果为所有promise结果的数组
* @param {array} promises
*/
Promise.all = function(promises) {
let resultArr = new Array(promises.length)
let count = 0
return new Promise((resolve, reject) => {
promises.forEach((promise, index) => {
Promise.resolve(promise).then(
value => {
count++
resultArr[index] = value
if (count === promises.length) {
resolve(resultArr)
}
},
reason => {
reject(reason)
}
)
})
})
}
/**
* 返回一个Promise, 结果为最先执行完的那个Promise的结果
* @param {array} promises
*/
Promise.race = function(promises) {
return new Promise((resolve, reject) => {
promises.forEach(promise => {
Promise.resolve(promise).then(resolve, reject)
})
})
}
window.Promise = Promise // 向外暴露Promise
})(window)
网友评论