最近在搞秋招,发现自己的还有很多不足,特地的来复习一下之前所学的知识,坐下笔记巩固一下
代码实现
类似于发布订阅模式的状态存储-来实现异步的回调
class Promise(){constructor(executor){ // executor 自执行函数this.state = 'pending' // 设置默认的状态 一共有 pending fulfilled rejectedthis.value = undefined // 设置成功时 存储返回的值this.reason = undefined // 设置失败时 存储失败的原因this.onFulfilledCallback = [] //存储成功时的回调函数this.onRejectedCallback = [];// 分别定义 resolve reject函数定义状态触发时的执行方法this.resolve = value=>{if(this.state === 'pending'){this.state = 'fulfilled'this.value = valuethis.onFulfilledCallback.forEach(fn=> f())}}this.reject = reason=>{if(this.tate === 'pending'){this.state = 'rejecteed'this.reason = reasonthis.onRejectedCallback.forEach(fn=> fn())}}try{executor(reslove,reject)}catch(e){reject(e)}}// 定义then方法then() .....}
实现then异步调用
class Promis(){constructor(executor){ .....then(onFulfilled,onRejected){// 如果没有函数的设置适配器(默认函数)onFulfilled = typeOf onFulfilled === 'function' ? onFulfilled : value=> value;onRejected = typeOf onRejected === 'function' ? onRejected : err = {throw err}let promise2 = new Promise((resolve,reject)=>{//三种状态// ————成功if(this.state === 'fulfilled'){setTimeout(()=>{var x = onFulfilleded(this.value) // 先执行当前then的回调函数, 并得到返回值reslovePromise(promise2,x,reslove,reject) // 如果有返回值执行自定义的函数},0)}// ———失败if(this.state === 'rejected'){setTimeout(()=>{var x = onRejected(this.value)reslovePromise(promise2,x,reslove,reject)},0)}// ———异步中(还在pending)if(this,state === 'pending'){ // 此时为异步调用分别将他们的函数推入定义的执行栈this.onFulfilledCallback.push(setTimeout(()=>{let x = oFulfilled(this.value)reslovePromise(promise2,x,reslove,reject)},0))this.onRejectedCallback.push({setTimeout(()=>{let x = onRejected(this.reason)reslovePromise(promise2,x,reslove,reject)},0)})}})}}
问题1——为啥能实现异步的回调呢
我们来看看最初实现异步操作的—回调
// f1 假设它为异步的操作function f1(){setTimeout(()=>{ja... 执行f1后面的操作f2(); // 执行f2()},1000)}//这样就保证了f2的在f1后面执行-保障了执行的顺序
我们来看看promise是怎么定义的
var p = new Promise(resolve=>{fs.readFile('input.txt', function (err, data) {if (err) {return console.error(err);}resolve(data)});})
她其实也是将后续操作(回调函数等)定义到后面,
1.所以当promise执行当then时发现异步函数还未执行完,于是将他推入执行栈内,
2.当异步函数执行完之后,执行resolve函数,这就像是自执行的订阅行为,(当异步函数还没执行完的时 候,发布其回调函数给promise,当执行完之后调用resolve订阅得到函数)
问题2——为啥要使用setTimout呢
如果在then方法注册回调之前,resolve函数就执行了,怎么办?比如promise内部的函数是同步函数
function getUserId() {return new Promise(function (resolve) {resolve(9876);});}getUserId().then(function (id) {// 一些处理});
Promises/A+规范明确要求回调需要通过异步方式执行,用以保证一致可靠的执行顺序。因此我们要加入一些处理,保证在resolve执行之前
实现relovePromise函数
function reslovePromise(promise2,x,reslove,reject){// 防止自身循环调用if(x === promise2){return reject(new TypeError('Chaining cycle detected for promise'))}let called = false // 检测他是否调用过if(x !== null && (typeof x === 'function' || typeof x === 'object')){// 返回的是一个promise对象try{const then = x.then;if(typeof then === 'fuction'){then.call(x,value=>{if(reject) returnreject = truereslovePromise(promise2,value,resolve,reject)},reason=>{if(reject) returnreject = truereject(reason)})}else{if(reject) returnreject = trueresolve(x)}}catch(e){if(reject) returnreject = truereject(e)}}else{// 返回的是一个普通的值relove(x)}}
问题3——什么时候会发生循环调用
let p = new Promise( resolve =>{resolve(x)})let p2 = p.then( ()=>{return p2})
问题4——为什么要使用try-catch语句
var obj = {};Object.defineProperty(obj,'a',{get:function () {return new Error('hhhhh');}})
当对象定义了defineProperty的时候,如获取属性时抛出错误,就会发生错误
问题4——called是干啥的
peomise要保证内的状态的变化是单向的,当一次执行时内部的状态发生了改变,就不允许再次调用;
