Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)
Promise对象的状态改变,只有两种可能:从pending->fulfilled或pending->rejected,一旦状态改变,结果不会再变
缺点
- 无法取消Promise,一旦新建它就会立即执行,无法中途取消
- 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部
- 当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
第一步基本实现
function Promise(executor){
this.status = 'pedding'
this.value = undefined
function resolve(data){
if(this.status !== 'pedding') return
this.status = 'fulfilled'
this.value = data
}
function reject(data){
if(this.status !== 'pedding') return
this.status = 'rejected'
this.value = data
}
try{
executor(resolve.bind(this), reject.bind(this))
}catch(err){
reject.bind(this, err)
}
}
Promise.prototype.then = function(onFulfilled, onRejected){
if(this.status === 'fulfilled'){
onFulfilled(this.value)
}
if(this.status === 'rejected'){
onRejected(this.value)
}
}
let p = new Promise((resolve, reject) => {
resolve(100)
})
p.then(data => {
console.log(data) //打印100
})
加入异步执行
此时无法打印结果,因为Promise会立即执行,then方法中status依然为pending
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(100)
}, 100)
})
p.then(data => {
console.log(data) //无法打印
})
改进后,在then中先将回调放入列队中,等状态改变后执行
function Promise(executor){
this.status = 'pedding'
this.value = undefined
this.fulfilledFunc = []
this.rejectedFunc = []
function resolve(data){
if(this.status !== 'pedding') return
this.status = 'fulfilled'
this.value = data
this.fulfilledFunc.forEach(item => item())
}
function reject(data){
if(this.status !== 'pedding') return
this.status = 'rejected'
this.value = data
this.rejectedFunc.forEach(item => item())
}
try{
executor(resolve.bind(this), reject.bind(this))
}catch(err){
reject.bind(this, err)
}
}
Promise.prototype.then = function(onFulfilled, onRejected){
if(this.status === 'pedding'){
this.fulfilledFunc.push(() => {
setTimeout(() => {
onFulfilled(this.value)
},0)
})
this.rejectedFunc.push(() => {
setTimeout(() => {
onRejected(this.value)
},0)
})
}
if(this.status === 'fulfilled'){
setTimeout(() => {
onFulfilled(this.value)
},0)
}
if(this.status === 'rejected'){
setTimeout(() => {
onRejected(this.value)
},0)
}
}
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(100)//1秒后打印
}, 1000)
})
p.then(data => {
console.log(data)
})
then
then方法是定义在Promise.prototype上,第一个参数是resolve状态的回调函数,第二个参数(可选)是reject状态的回调函数
then方法返回的是一个新的Promise实例,因此可以采用链式写法
Promise.prototype.then = function(onFulfilled, onRejected){
return new Promise((resolve, reject) => {
if(this.status === 'pedding'){
this.fulfilledFunc.push(() => {
setTimeout(() => {
try{
onFulfilled(this.value)
}catch(e){
reject(e)
}
},0)
})
this.rejectedFunc.push(() => {
setTimeout(() => {
try{
onRejected(this.value)
}catch(e){
reject(e)
}
},0)
})
}
if(this.status === 'fulfilled'){
setTimeout(() => {
try{
onFulfilled(this.value)
}catch(e){
reject(e)
}
},0)
}
if(this.status === 'rejected'){
setTimeout(() => {
try{
onRejected(this.value)
}catch(e){
reject(e)
}
},0)
}
})
}
试试链式调用
let p = new Promise((resolve, reject) => {
resolve(100)
})
let p2 = p.then(data => {
console.log(123)
return data
}).then(data => {
console.log(data)
})
发现第一个then输出了 第二个then没有执行,因为我们的then方法没有将返回值向下一个promise传递
then方法片段
if(this.status === 'fulfilled'){
setTimeout(() => {
try{
//获取第一个then的返回值,没有返回值则为undefined
let x= onFulfilled(this.value)
//向下一个then传递
resolvePromise(x, resolve, reject)
}catch(e){
reject(e)
}
},0)
}
resolvePromise
function resolvePromise(x, resolve, reject) {
if(x != null && (typeof x === 'object') || (typeof x === 'function')){
} else {
resolve(x);
}
}
在第一个then中返回promise
let p = new Promise((resolve, reject) => {
resolve(100)
})
let p2 = p.then(data => {
return new Promise((resolve, reject) => {
resolve(1000)
})
})
p2.then(data => {
console.log(data)
})
发现没有返回,我们继续完善resolvePromise
function resolvePromise(x, resolve, reject) {
if(x != null && (typeof x === 'object') || (typeof x === 'function')){
if(typeof x.then === 'function'){
x.then(data => {
resolve(data)
}, err => {
reject(err)
})
}else{
resolve(x)
}
} else {
resolve(x);
}
}
此时可以返回了,我们继续promise resolve promise
let p = new Promise((resolve, reject) => {
resolve(100)
})
let p2 = p.then(data => {
return new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {
resolve(1000)
}))
})
})
p2.then(data => {
console.log(data)
})
此时没有返回值了,我们继续完善resolvePromise
function resolvePromise(x, resolve, reject) {
if(x != null && (typeof x === 'object') || (typeof x === 'function')){
if(typeof x.then === 'function'){
x.then(data => {
//递归执行
resolvePromise(data, resolve, reject)
}, err => {
reject(err)
})
}else{
resolve(x)
}
}else {
resolve(x);
}
}
好了,我们完善一下then
Promise.prototype.then = function(onFulfilled, onRejected){
return new Promise((resolve, reject) => {
if(this.status === 'pedding'){
this.fulfilledFunc.push(() => {
setTimeout(() => {
try{
let x = onFulfilled(this.value)
resolvePromise(x, resolve, reject);
}catch(e){
reject(e)
}
},0)
})
this.rejectedFunc.push(() => {
setTimeout(() => {
try{
let x = onRejected(this.value)
resolvePromise(x, resolve, reject);
}catch(e){
reject(e)
}
},0)
})
}
if(this.status === 'fulfilled'){
setTimeout(() => {
try{
let x = onFulfilled(this.value)
resolvePromise(x, resolve, reject);
}catch(e){
reject(e)
}
},0)
}
if(this.status === 'rejected'){
setTimeout(() => {
try{
let x = onRejected(this.value)
resolvePromise(x, resolve, reject);
}catch(e){
reject(e)
}
},0)
}
})
}
Promise.all
Promise.all等参数中的promise都fulfilled了返回结果,如果有一个状态rejected结果则为rejected
Promise.all = function(arr){
return new Promise((resolve, reject) => {
const list = []
arr.forEach((item, index ) => {
item.then(data => {
list.push(data)
if(list.length === arr.length){
resolve(list)
}
}, err => {
reject(err)
})
})
})
}
测试一下
Promise.all([
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(100)
}, 1000)
}),
new Promise((resolve, reject) => {
resolve(1000)
})
]).then(data => {
console.log(data) //返回[100, 1000]
})
Promise.race
Promise.race参数中有一个promise改变状态了,这率先返回结果
Promise.race = function(arr){
return new Promise((resolve, reject) => {
arr.forEach((item, index ) => {
item.then(data => {
resolve(data)
}, err => {
reject(err)
})
})
})
}
测试一下
Promise.race([
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(100)
}, 1000)
}),
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1000)
}, 2000)
})
]).then(data => {
console.log(data)/返回100
})
Promise.resolve
Promise.resolve = function(value){
return new Promise((resolve,reject) => {
resolve(value)
})
}
Promise.reject
Promise.resolve = function(value){
return new Promise((resolve,reject) => {
reject(value)
})
}