问题
我们带着问题去看源码promsie
- promise 是什么,主要用来解决什么
- promise 源码是如何进行解决的?
- promise 有哪些实例方法和静态方法
- promise 为什么可以进行链式调用
- 怎样实现promise状态的不可逆
promise是什么?
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大,就是用同步的书写代码方式来替代回调地狱式的写法
promise 的状态
- pending
- fulfilled
- rejected
promise的状态是不可逆的,只能从一种状态改变成另一种状态 ,一旦状态改变,就不会再变,Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。 因此可以相爱下面代码做了判断 在执行resolve的时候把状态改了,rejected的时候状态也变了
promise 的原型上的方法
promise 的原型上的方法也称为实例方法
- then
- catch
- finally
promise 的静态方法
promise 静态方法就是构造函数上的方法
- all
- race
- resolve
- reject
promise源码
// 这个函数的作用主要就是判断x 是不是普通的值还是promsie
// 然后返回对应的成功状态或者失败状态进行传递值
function resolvePromise(promsie2, x, resolve, reject) {
// 判断promise 是否等于自身
// 如下面这种情况,就会出现等于自身的情况
// let p = new Promise1((resove,reject)=>{
// resove()
// })
// let p2 = p.then((value)=>{
// console.log('成功',value)
// return p2
// },(value)=>{
// console.log('失败',value)
// return 'hhhh'
// })
// p2.then(()=>{
// console.log('哈哈哈')
// },(err)=>{
// console.log('www',err)
// })
if (promsie2 === x) {
return reject(new TypeError(' Chaining cycle detected for promise #<Promise>'))
}
let called; // 为了防止掉了成功 又调用失败
// 然后就是判断x的类型 是否是常量 还是promise
// 如何判断promise 是不是一个promise 看他有没有then方法
if (typeof x === 'function' || (typeof x === 'object' && x != null)) {
try {
let then = x.then // then方法可能会出错
if (typeof then === 'function') {
then.call(x, y => { // 如果promise是成功的就把结果向下传,如果失败的就让下一个也失败
if (called) return
called = true
resolvePromise(promsie2, y, resolve, reject) // 递归 为了防止then一层层为promise
// resolve(y)
}, r => {
if (called) return
called = true
reject(r)
}) // 不要使用x.then 否则会再次取值s
} else {
resolve(x)
}
} catch (e) {
if (called) return
called = true
reject(e)
}
} else {
resolve(x)
}
}
class Promise {
constructor(extruct) {
this.state = 'pending'
this.value = undefined; //成功的值
this.reason = undefined //失败的原用
this.onResovleCallbacks = []
this.onRejectedCallbacks = []
let resolve = (value) => {
// 为了防止这种情况发生
// let p = new Promise((resove,reject)=>{
// resove(new Promise((resove,reject)=>{
// resove(100)
// }))
// })
if (value instanceof Promise) {
// debugger
return value.then(resolve, reject)
}
if (this.state === 'pending') {
// debugger
this.state = 'resolve'
this.value = value
this.onResovleCallbacks.forEach(fu => fu())
}
}
let reject = (value) => {
if (this.state === 'pending') {
this.state = 'reject'
this.reason = value
this.onRejectedCallbacks.forEach(fu => fu())
}
}
// try 方法 可能会在调用Promise 的时候直接出催
try {
extruct(resolve, reject)
} catch (e) {
reject(e)
}
}
catch(errCallbak){ // 用来捕获错误的 .then(null,err=>err)
return this.then(null,errCallbak)
}
then(onFulfilled, onRejected) {
// debugger
// 为了防止值的穿透事件
// 例如这种情况
// let p = new Promise((resove,reject)=>{
// reject()
// })
// p.then(()=>{}).then(()=>{},(ee)=>{
// console.log(111)
// })
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : data => data
onRejected = typeof onRejected === 'function' ? onRejected : (err) => { throw err }
let promsie2
// 在promise中实现链式调用 靠的不是返回this
// 因为 promise 的状态是不可逆的
// 所以是返回了一个新的 promise
promsie2 = new Promise((resolve, reject) => {
if (this.state === 'resolve') {
// setTimeout 的目的是为了获取 promsie2
// 因为在刚开始的时候 promsie2 是不存在的
setTimeout(() => {
// debugger
// x 为常量 x 为promise
// resolve(x)
try {
let x = onFulfilled(this.value)
// 这个函数主要目的是为了区分 x 是常量还是promise
resolvePromise(promsie2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
// debugger
if (this.state === 'reject') {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promsie2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.state === 'pending') {
this.onResovleCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promsie2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promsie2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
})
return promsie2
}
finally(callback){
return this.then((data)=>{
return new Promise((resolve,reject)=>{
resolve(callback)
}).then(()=>data)
},err=>{
return new Promise((resolve,reject)=>{
resolve(callback)
}).then(()=>{throw err})
})
}
}
// 其实就是返回了一个成功的promsie
Promise.resolve = function(value){
return new Promise((resolve,reject)=>{
resolve(value)
})
}
// 这是tj大神写的co库判断是否是isPromise的代码就是判断有没有then方法
// 如果有的话就是promsie
// function isPromise(obj) {
// return 'function' == typeof obj.then;
// }
// 判断是否是promise
function isPromise(value){
if(typeof value ==='function'|| (typeof value ==='object'&& typeof value !=null)){
if(typeof value.then ==='function'){
return true
}
}else{
return false
}
}
// Promise.all 接收的是一个数组作为参数
// 能够进行链式调用.then方法 因此内部是返回了一个promise
Promise.all = function(values){
return new Promise((resolve,reject)=>{
let arr = []
let i=0;
let processDate = (index,val)=>{
arr[index] = val
i++
if(i===values.length){
resolve(arr)
}
// 这里用 i++
// 是为了防止 a[1]
// 有值了 而a[0] 还没有值 就会出现a[0]没有收到值而reolve()
}
// values 有可能会这样[promise,promise,1,2],
// 所以要判断是否是promsie
for(let i=0;i<values.length;i++){
let cuurent = values[i]
if(isPromise(cuurent)){
cuurent.then((val)=>{
processDate(i,val)
},(err)=>{
reject(err)
})
}else{
processDate(i,cuurent)
}
}
})
}
进行promise 测试
- 在promise.js下面增加这样一段话
- 测试参考地址
Promise.defer = Promise.deferred = function () {
let dfd = {}
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
module.exports = Promise
- 可以全局安装 promises-aplus-tests
npm install promises-aplus-tests -g
- 进行测试
promises-aplus-tests ./promise.js