promiss
- 规范: promissoryA+ https://promisesaplus.com/
基础版
**promise解决的问题 **
-
等待多个异步请求结束 promise.all
-
链式调用,上一个请求结果是下一个请求的参数等,解决回调地狱 promise.then
_ 缺陷: 还是基于回调的,只是写法更优雅
promise 的特点
- promise 是个类
- promise有三个状态, resolve(成功) reject(失败) pendding(等待)
- promise 默认执行器立即执行
- 用户可以自己决定成功还是失败的状态
- promise都有then方法,默认有两个参数,成功的回调,可以拿到成功态的参数;失败的回调,可以拿到失败态的参数
- 如果执行函数时发生了异常,就走到了失败态
- 一旦成功态了就不能再失败了,失败态也不能再转到成功; 状态不可逆转
// 简单版promise
const RESOLVED = 'RESOLVED'
const REJECTED = 'REJECTED'
const PENDDING = 'PENDDING'
class Promise1 {
constructor(executor) {
this.value = undefined
this.reason = undefined
this.state = PENDDING
let resolve = (data) => {
if (this.state === PENDDING) {
console.log()
this.state = RESOLVED
this.value = data
}
}
let reject = (data) => {
if (this.state === PENDDING) {
this.state = REJECTED
this.reason = data
}
}
try {
// throw new Error("抛出错误");
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
then(onFulfilled, onRejected) {
if (this.state === RESOLVED) {
onFulfilled(this.value)
}
if (this.state === REJECTED) {
onRejected(this.reason)
}
}
}
let p = new Promise1((resolve, reject) => {
console.log('立即执行')
resolve('成功')
// reject('失败啦')
})
p.then((res) => { console.log('成功', res) }, (err) => { console.log('失败' + err) })
异步 调用
上面简版promise
待解决问题有1️⃣ promise 调用then时,如果异步,resolve或者reject没有完成, pedding状态,不能拿到执行后的额结果
解决方法:用发布订阅模式, then的成功回调和失败回调都存起来, 等异步结束,pengdding状态改变,再依次执行
const RESOLVED = 'RESOLVED'
const REJECTED = 'REJECTED'
const PENDDING = 'PENDDING'
class Promise1 {
constructor(executor) {
this.value = undefined
this.reason = undefined
this.state = PENDDING
// ---------- 新增代码
this.onResolvedCallbacks = []
this.onRejectedCallbacks = []
//-------
let resolve = (data) => {
if (this.state === PENDDING) {
console.log()
this.state = RESOLVED
this.value = data
// -------- 发布事件
this.onResolvedCallbacks.forEach(i => i())
// --------
}
}
let reject = (data) => {
if (this.state === PENDDING) {
this.state = REJECTED
this.reason = data
// ----- 发布事件
this.onRejectedCallbacks.forEach(i => i())
// -----
}
}
try {
// throw new Error("loopTerminates");
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
then(onFulfilled, onRejected) {
if (this.state === RESOLVED) {
onFulfilled(this.value)
}
if (this.state === REJECTED) {
onRejected(this.reason)
}
// -------------- 异步,状态为pendding,先订阅事件
if (this.state === PENDDING) {
this.onResolvedCallbacks.push(() => {
onFulfilled(this.value)
})
this.onRejectedCallbacks.push(() => {
onRejected(this.reason)
})
}
// ---------------
}
}
let p = new Promise1((resolve, reject) => {
console.log('立即执行')
setTimeout(() => {
resolve('成功')
}, 200);
// reject('失败啦')
})
p.then((res) => { console.log('成功', res) }, (err) => { console.log('失败' + err) })
p.then((res) => { console.log('成功2', res) }, (err) => { console.log('失败2' + err) })
then特性
promise then 特性
-
promise 失败和成功的返回值可以传递到下一个then里面
-
如果返回值是普通值, 传递到下一个then的成功回调里.
如果抛出错误,传递到失败回调里;
如果返回值是promise,则根据promise的结果,resolve就传递到成功回调,reject就传递到失败回调里
-
错误处理,如果最近的then里面没有错误处理,会向下找错误回调,处理错误
-
promise.then返回一个新的promise 而不是this(因为promise状态不可逆,不会成功转失败等)
const RESOLVED = 'RESOLVED'
const REJECTED = 'REJECTED'
const PENDDING = 'PENDDING'
// -------根绝返回值x确定如果处理promise结果
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) { // 自己调自己,报类型错误
throw new Error('TypeError')
}
let called; // unfined 用于处理别人得posmise可能出现先成功又失败等情况;
if ((typeof x === 'object' && x != null) || typeof x === 'function') {
try {
// x 是对象或者函数,有可能是promise
let then = x.then
if (typeof then === 'function') {
// 假定是promise
then.call(x, y => {
if (called) return
called = true // 成功,失败,异常,只能调用一次,promise状态不能更改
// 成功回调
resolvePromise(promise2, y, resolve, reject) // 递归解析,如果resolve返回一个promise
}, e => {
if (called) return
called = true
// 失败回调
reject(e)
})
} else { // 普通对象,刚好有then方法
resolve(x)
}
} catch (e) {
if (called) return
called = true
reject(e)
}
} else { // x 是普通值
resolve(x)
}
}
// --------方法结束
class Promise1 {
constructor(executor) {
this.value = undefined
this.reason = undefined
this.state = PENDDING
this.onResolvedCallbacks = []
this.onRejectedCallbacks = []
let resolve = (data) => {
if (this.state === PENDDING) {
console.log()
this.state = RESOLVED
this.value = data
this.onResolvedCallbacks.forEach(i => i())
}
}
let reject = (data) => {
if (this.state === PENDDING) {
this.state = REJECTED
this.reason = data
this.onRejectedCallbacks.forEach(i => i())
}
}
try {
// throw new Error("loopTerminates");
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
then(onFulfilled, onRejected) {
// 返回的promise2
let promise2 = new Promise1((resolve, reject) => {
if (this.state === RESOLVED) {
setTimeout(() => { // 异步,才能在下面resolvePromise中拿到promise2的值
// 1,x是普通值,还是promise? 2,怎么处理x
try {
let x = onFulfilled(this.value)
// 处理x和promise返回值
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
}
if (this.state === REJECTED) {
setTimeout(() => { // 异步,才能在下面resolvePromise中拿到promise2的值
// 1,x是普通值,还是promise? 2,怎么处理x
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
}
if (this.state === PENDDING) {
this.onResolvedCallbacks.push(() => {
setTimeout(() => { // 异步,才能在下面resolvePromise中拿到promise2的值
// 1,x是普通值,还是promise? 2,怎么处理x
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => { // 异步,才能在下面resolvePromise中拿到promise2的值
// 1,x是普通值,还是promise? 2,怎么处理x
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
}
})
return promise2
}
}
let p1 = new Promise1((resolve, reject) => {
throw new Error('抛出错误信息');
resolve('111')
})
let p2 = p1.then((data) => {
return new Promise1((resolve, reject) => {
setTimeout(() => {
resolve(new Promise1((resolve, reject) => {
resolve('20000')
}))
}, 500)
})
}, e => {
console.log('===', e)
})
// reject('失败啦')
p2.then((res) => { console.log('成功', res) }, (err) => { console.log('失败' + err) })
最终版
- 添加then穿透,; resolve,reject传参不是function时,自动补全函数,参数下传
- promises-aplus-tests promise规则校验
const RESOLVED = 'RESOLVED'
const REJECTED = 'REJECTED'
const PENDDING = 'PENDDING'
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) { // 自己调自己,报类型错误
return reject(new TypeError('TypeError'))
}
let called; // unfined 用于处理别人得posmise可能出现先成功又失败等情况;
if ((typeof x === 'object' && x != null) || typeof x === 'function') {
try {
// x 是对象或者函数,有可能是promise
let then = x.then
if (typeof then === 'function') {
// 假定是promise
then.call(x, y => {
if (called) return
called = true // 成功,失败,异常,只能调用一次,promise状态不能更改
// 成功回调
resolvePromise(promise2, y, resolve, reject) // 递归解析,如果resolve返回一个promise
}, e => {
if (called) return
called = true
// 失败回调
reject(e)
})
} else { // 普通对象,刚好有then方法
resolve(x)
}
} catch (e) {
if (called) return
called = true
reject(e)
}
} else { // x 是普通值
resolve(x)
}
}
class Promise1 {
constructor(executor) {
this.value = undefined
this.reason = undefined
this.state = PENDDING
this.onResolvedCallbacks = []
this.onRejectedCallbacks = []
let resolve = (data) => {
if (this.state === PENDDING) {
console.log()
this.state = RESOLVED
this.value = data
this.onResolvedCallbacks.forEach(i => i())
}
}
let reject = (data) => {
if (this.state === PENDDING) {
this.state = REJECTED
this.reason = data
this.onRejectedCallbacks.forEach(i => i())
}
}
try {
// throw new Error("loopTerminates");
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
then(onFulfilled, onRejected) {
// onFulfilled, onRejected 可选参数,如果没有值,默认透传
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }
let promise2 = new Promise1((resolve, reject) => {
if (this.state === RESOLVED) {
setTimeout(() => { // 异步,才能在下面resolvePromise中拿到promise2的值
// 1,x是普通值,还是promise? 2,怎么处理x
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
}
if (this.state === REJECTED) {
setTimeout(() => { // 异步,才能在下面resolvePromise中拿到promise2的值
// 1,x是普通值,还是promise? 2,怎么处理x
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
}
if (this.state === PENDDING) {
this.onResolvedCallbacks.push(() => {
setTimeout(() => { // 异步,才能在下面resolvePromise中拿到promise2的值
// 1,x是普通值,还是promise? 2,怎么处理x
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => { // 异步,才能在下面resolvePromise中拿到promise2的值
// 1,x是普通值,还是promise? 2,怎么处理x
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
}
})
return promise2
}
}
// let p1 = new Promise1((resolve, reject) => {
// reject('222')
// throw new Error('抛出错误信息');
// resolve('111')
// })
// let p2 = p1.then((data) => {
// return new Promise1((resolve, reject) => {
// setTimeout(() => {
// resolve(new Promise1((resolve, reject) => {
// resolve('20000')
// }))
// }, 500)
// })
// }, e => {
// console.log('===', e)
// })
// reject('失败啦')
// p1.then().then().then((res) => { console.log('成功', res) }, (err) => { console.log('失败' + err) })
// 用 promises-aplus-tests 进行测试
Promise1.defer = Promise1.deferred = function () {
let dfd = {};
dfd.promise = new Promise1((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
module.exports = Promise1