1、什么是Promise?
Promise是ECMAscript 6原生提供的一个对象,用来传递异步操作的消息
2、Promise的基础用法
new Promise((resovle, rejcet) => {
resovle('first resolve')
}).then(res => {
console.log('first then:', res)
return 'first then'
}).then(res => {
console.log('second then', res)
return new Promise((resolve, rejcet) => {
rejcet('second new Promise reject')
})
}).then(()=> {
}, err => {
console.log('last then reject: ', err)
})
// 或者使用catch 去处理reject
new Promise((resovle, rejcet) => {
resovle('first resolve')
}).then(res => {
console.log('first then:', res)
return 'first then'
}).then(res => {
console.log('second then', res)
return new Promise((resolve, rejcet) => {
rejcet('second new Promise reject')
})
}).catch(err => {
console.log('last then reject: ', err)
})
3、Promise/A+规范(参考链接)总结
- Promise有三种状态,pending、fullfilled、rejected
- Promise的初始状态是pending,如果Promise的状态是pending,那么这个promise可能转换到fullfilled或者rejected, 如果promise的状态是fullfilled或者rejected, 那个这个promise的状态是不可以改变的
- 要有then方法(thenable),通过then方法可以获取成功的value以及失败的reason
- then方法接受两个参数 onFullfilled和onRejected,这两个参数如果存在,一定是函数,如果不是函数那么就要忽略。
- 在then方法执行的时候,如果状态为fullfilled那么执行onFullfilled方法, 如果状态为rejected,那么执行onRejected方法
- then方法返回的是一个Promise
4、代码实现
首先我们分析一下Promise, Promsie是可以new的,所以Promise是个Function或者Class,在实例化Promise的时候,构造函数传如的是一个执行器,有then方法,then方法有两个入参,分别是成功的回调和失败的回调
现在我们要实现下面的Promise用法
new MyPromise((resolve, reject) => {
resolve(1)
}).then(res => {
console.log(res)
})
实现代码
(1)设定三种状态
const FULLFILLED = 'fullfilled',
PNEDING = 'pending',
REJECTED = 'rejected'
(2)写Promise的构造函数:
promise的初始状态为Pending,value接受成功值,reason接受失败值,然后顶一个resolve方法,resolve的作用是改变promise状态以及value值;定义reject方法,rejcet方法的作用是改变promise的状态以及reason值
class MyPromise {
constructor(exector) {
this.state = PNEDING
this.value
this.reason
this.onFullfilledCallbacks = []
this.onRejectedCallbacks = []
let resolve = (value) => {
if (this.state === PNEDING) {
this.value = value
this.state = FULLFILLED
}
}
let reject = (reason) => {
if (this.state === PNEDING) {
this.reason = reason
this.state = REJECTED
}
}
exector(resolve, reject)
}
}
(3)写then方法
then(onFullfilled, onRejceted) {
if (this.state === FULLFILLED) {
onFullfilled(this.value)
}
if (this.state === REJECTED) {
x = onRejceted(this.reason)
}
}
这样我们的ProiseV0.0.0.0.0.0.1就写好了:》
但是这个promise太简单了,处理不了异步的情况例如我们在settimeout之后进行resolve,在then方法中就拿不到resolve的值,因为在执行then方法的时候,promise的状态是pending,所以现有的then方法判断不到
new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000);
}).then(res => {
console.log(res)
})
我们要进行改造,在构造函数中增加onRejected, onFullfilled回调集合;回调集合对then方法进行改造判断Pending状态,增加
constructor(exector) {
this.state = PNEDING
this.value
this.reason
this.onFullfilledCallbacks = []
this.onRejectedCallbacks = []
let resolve = (value) => {
if (this.state === PNEDING) {
this.value = value
this.state = FULLFILLED
this.onFullfilledCallbacks.forEach(fn => fn())
}
}
let reject = (reason) => {
if (this.state === PNEDING) {
this.reason = reason
this.state = REJECTED
this.onRejectedCallbacks.forEach(fn => fn())
}
}
exector(resolve, reject)
}
then(onFullfilled, onRejceted) {
if (this.state === FULLFILLED) {
onFullfilled(this.value)
resolvePromise(p2, x, resolve, rejcet)
}
if (this.state === REJECTED) {
onRejceted(this.reason)
resolvePromise(p2, x, resolve, rejcet)
}
if (this.state === PNEDING) {
this.onFullfilledCallbacks.push(() => {
onFullfilled(this.value)
})
this.onRejectedCallbacks.push(() => {
onRejceted(this.reason)
})
}
return p2
}
在pending的时候我们收集onFullfilled和onReject函数,然后在resolve或者reject方法执行的时候,对收集的方法进项执行
但是现在的Promise是不能链式调用的, 所以接下来我偷懒。(其实自己想想,就是then方法会返回一个promise,并且执行这个promise的resolve,或者是reject,并且把then方法上一次执行的返回值,放到下一次resolve中,因为我们不能确定then的回调返回的是普通值还是promise, 所以我们要进行递归,直到返回值是一个普通值为止)
then(onFullfilled, onRejceted) {
let x
let p2 = new MyPromise((resolve ,rejcet) => {
if (this.state === FULLFILLED) {
setTimeout(() => {
x = onFullfilled(this.value)
resolvePromise(p2, x, resolve, rejcet)
}, 0)
}
if (this.state === REJECTED) {
setTimeout(() => {
x = onRejceted(this.reason)
resolvePromise(p2, x, resolve, rejcet)
}, 0);
}
if (this.state === PNEDING) {
this.onFullfilledCallbacks.push(() => {
setTimeout(() => {
x = onFullfilled(this.value)
resolvePromise(p2, x, resolve, rejcet)
}, 0);
})
this.onRejectedCallbacks.push(() => {
onRejceted(this.reason)
})
}
})
return p2
}
我们用resolvePromise方法处理返回值
function resolvePromise(p2, x, resolve, reject) {
if (p2 === x) throw new Error('...!')
// 如果满足这个条件我们就认为这是一个promise
if(typeof x === 'object' && x !== null || typeof x === 'funciton') {
if (x.then && typeof x.then === 'function') {
let then = x.then
then.call(x, y => {
resolve(y)
}, err => {
reject(err)
})
} else {
resolve(x)
}
} else {
// 啊!!! 我是一个普通值 int sting number boolean
resolve(x)
}
}
这样一个简易的Promise就写好了,当然中间还有好多细节,后续会更新完整版谢谢!!:)