关于异步的解决方案目前有四种:
- callback(回调函数)
- generato + co库
- promise
- async+await
promise的基本特点:
- promise代表的是承诺的意思 promise最核心的就是有三个状态,等待态(pending), 成功态(fulfilled)
,失败态(rejected) - 状态只能从等待态改变成其他状态 ,不能从成功变成失败,也不能从失败变成成功
- 默认你传入的executor会立刻执行, 这个executor函数接受两个参数 resolve,reject 都是函数类型
- 在代码中发生异常也是会走失败的情况
封装基本的promise :
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILLED
this.value = value;
this.onResolvedCallbacks.forEach(fn=>fn());
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason;
this.onRejectedCallbacks.forEach(fn=>fn());
}
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
if(this.status ===FULFILLED ){
onFulfilled(this.value);
}
if(this.status === REJECTED){
onRejected(this.reason)
}
if(this.status === PENDING){
this.onResolvedCallbacks.push(()=>{
onFulfilled(this.value);
});
this.onRejectedCallbacks.push(()=>{
onRejected(this.reason);
})
}
}
}
测试验证:
let promise = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('1111');
},1500)
});
promise.then((value)=>{
console.log('success',value)
},(reason)=>{
console.log('fail',reason)
})
promise.then((value)=>{
console.log('success',value)
},(reason)=>{
console.log('fail',reason)
})
封装完基本版本后,还存在的问题: 1.then不是异步的 ,如果直接调用resolve完后是同步执行,比如:
let promise = new Promise((resolve,reject)=>{
resolve('1111');
});
promise.then((value)=>{
console.log('success',value)
},(reason)=>{
console.log('fail',reason)
})
promise.then((value)=>{
console.log('success',value)
},(reason)=>{
console.log('fail',reason)
})
console.log('end');
结果是先输出:success 1111,再试end 2.我们newPromise 直接resolve了 ,会将resolve的参数传递到了下一次then中,then中传递的成功和失败的回调的返回值, 会决定下一个then 走成功还是失败,比如:
let promise2 = new Promise((resolve,reject)=>{
resolve('ok')
})
promise2.then(data=>{
return 'next'
},()=>{
return 'fail'
}).then((data)=>{
console.log('success',data)
},(err)=>{
console.log('fail',err)
})
该代码输出的正确结果,应该是 success next ,但输出却是报错的,因为then并没有返回值
进阶版promise实现:
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'
function resolvePromise(promise2, x, resolve, reject) {
if (x) {
try {
resolve(x);
} catch (e) {
reject(e);
}
} else {
resolve(x);
}
}
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if(value instanceof Promise){
return value.then(resolve,reject)
}
if (this.status === PENDING) {
this.status = FULFILLED
this.value = value;
this.onResolvedCallbacks.forEach(fn => fn());
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
let promise2 = new Promise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === PENDING) {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e);
}
}, 0)
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e);
}
}, 0)
})
}
});
return promise2
}
}
结果:
let promise = new Promise((resolve,reject)=>{
resolve('1111');
});
promise.then((value)=>{
console.log('success',value)
},(reason)=>{
console.log('fail',reason)
})
promise.then((value)=>{
console.log('success',value)
},(reason)=>{
console.log('fail',reason)
})
console.log('end');
能正确输出结果:
let promise2 = new Promise((resolve,reject)=>{
resolve('ok')
})
promise2.then(data=>{
return 'next'
},()=>{
return 'fail'
}).then((data)=>{
console.log('success',data)
},(err)=>{
console.log('fail',err)
})
正确输出结果:
当然上面进阶版的实现也不是最终完整版的,最终的版本会有很多类型判断,我也是把基本代码跑通了而已,面试的时候,基本版本就够用了,毕竟也不会给这么多时间你写,哈哈
|