筹备工作
实现一个高阶函数
调用一个办法,在这个办法执行前先执行另一个办法
// AOP 切片编程function say(who){ console.log(who + '谈话了');}//在函数的原型对象上增加一个属性berfor 能够让每个函数都能调用Function.prototype.berfor = function(berforFunc){ return (...agrs)=>{ berforFunc() this(...agrs) }}let newFn = say.berfor(function(){ console.log('谈话之前');})newFn('我')// ======================================================let oldPush = Array.prototype.push;function push(...agrs){ // this ===》 arr console.log('数据更新了'); oldPush.call(this,...agrs); // call 1、扭转this指向 2、让函数执行}let arr = [1,2,3]// push(arr,4,5,6) // 在这调用push办法时,this的指向是全局, 所以应用call 扭转this指向push.call(arr,4,5,6) // 在这调用push办法时,this的指向是全局,对应的函数外部也是全副, 所以应用call 扭转this指向console.log(arr)
AOP
AOP(面向切面编程)的次要作用是把一些跟外围业务逻辑模块无关的性能抽离进去,其实就是给函数加一层,不必管函数外部实现
成果代码:
function perform(anyMethod,wrappers){ return function(){ wrappers.forEach(wrapper => wrapper.initialize()) anyMethod() wrappers.forEach(wrapper => wrapper.close()) }}let newFn1 = perform(function(){ console.log('say')},[{ initialize(){ console.log('wrapper1 beforeSay') }, close(){ console.log('wrapper1 close') } }, { initialize(){ console.log('wrapper2 beforeSay') }, close(){ console.log('wrapper2 close') } }])newFn1()// wrapper1 beforeSay// wrapper2 beforeSay// say// wrapper1 close// wrapper2 close
after 在 。。。 之后
// 利用闭包 保留times 在执行两次后才会输入function after(times,callback){ return function(){ if(--times === 0){ callback() } }}let fn = after(2, function(){ console.log('really')})fn();fn();
应用高阶函数解决异步问题的思路
let fs = require('fs')fs.readFile('./name.txt','utf8',function(err,res){ // console.log(res) // 第一种办法应用 school.name = res out() // 第二种办法应用 out('name',res)})fs.readFile('./age.txt','utf8',function(err,res){ // console.log(res) // 第一种办法应用 school.age = res out() // 第二种办法应用 out('name',res)})// 第一种 应用回调函数的办法 然而这个办法 会导致school裸露再里面 //都能够批改 school,所哟并不是黑号let school = {}function out(){ console.log(Object.keys(school)) if(Object.keys(school).length == 2){ console.log(school) }}// 第二种 应用 上述after的办法来实现,,也就是闭包的模式let out = after(2, function(res){ console.log(res)})function after(times,callback){ let school = {} return function(key,val){ school[key] = val if(--times === 0){ callback(school) } }}
公布模式和订阅模式
let fs = require('fs')fs.readFile('./name.txt','utf8',function(err,res){ school.name = res event.emit()})fs.readFile('./age.txt','utf8',function(err,res){ school.age = res event.emit()})let event = { _arr:[], // 订阅 on:function(fn){ this._arr.push(fn) }, // 公布 emit:function(fn){ this._arr.forEach(fn => fn()) }}let school = {}event.on(function(){ console.log('读取一个');})event.on(function(){ if(Object.keys(school).length == 2){ console.log(school) }})
观察者模式 是基于公布订阅模式的
// 被观察者class Subject{ constructor(){ this.state = '开心' this.arr = [] } // 增加观察者 attach(o){ this.arr.push(o) } // 设置状态 并触发 setState(newState){ this.state = newState this.arr.forEach(o=>o.update(newState)) }}// 观察者class Observer{ constructor(name){ this.name = name } // 当观察者被批改后,会触发该办法 update(newState){ console.log(this.name+':'+'小宝宝'+newState) }}let sub = new Subject('小宝宝')let my = new Observer('我')sub.attach(my)sub.setState('不开心')sub.setState('很开心')
开始promise
promise优缺点
长处
- 能够解决异步嵌套问题
- 能够解决多个异步并发问题
毛病
- promise 基于回调 会不停的写函数
- 无奈终止异步
根本实现 与 then办法
/** * 1、(then中传递的函数)判断胜利和失败函数的返回后果 * 2、判断是不是promise 如果是promise 就采纳他的状态 * 3、如果不是promise 间接将后果传递上来即可 */const PENDING = 'PENDING'const FULFILLED = 'FULFILLED'const REJECTED = 'REJECTED'// 因为promise const resolvePromise = (_promise, x, fulfill, reject) => { let called; // x 和 promise 不能是同一个 promise mdn中有解释 将会进入死循环 (promise 标准) if (x === _promise) { return reject(new TypeError('Chaining cycle detected for promise #<Promise>')) } if (typeof x === 'object' && x !== null || typeof x === 'function') { try { let then = x.then // 取then 有可能then属性是通过 defineProperty来定义的 if (typeof then === 'function') { // 当then是一个办法 就认为是promise then.call(x, y => { if(called) return; called = true resolvePromise(_promise, y, fulfill, reject) // 参用promise 的胜利后果向下传 递归 晓得解析进去的是一个一般值 }, r => { if(called) return; called = true reject(r) // 采纳失败后果向下传 }) // 能保障不必再次then的值 } else { fulfill(then) // 阐明x是一个一般对象 } } catch (e) { if(called) return; called = true reject(e) } } else { fulfill(x) }}class MyPromise { // 1 看属性是否再原型上 // 2 看属性是否专用 constructor(executor) { this.status = PENDING this.value = undefined; this.reason = undefined; this.onFulfilledCallbacks = []; // 胜利的函数数组 this.onRejectedCallbacks = []; // 失败的函数数组 // 胜利函数 let fulfill = (value) => { if (this.status === PENDING) { // 屏蔽 this.value = value this.status = FULFILLED this.onFulfilledCallbacks.forEach(fn => fn()) } } // 失败函数 let reject = (reason) => { console.log('reason: ' + reason) if (this.status === PENDING ) { // 屏蔽 this.reason = reason this.status = REJECTED this.onRejectedCallbacks.forEach(fn => fn()) } } try { executor(fulfill, reject); // 默认执行器会立即执行 } catch (e) { reject(e) // 如果执行失败产生谬误 等价于调用了 } } // 传入两个参数 then(onFulfilled = data => data, onRejected) { onRejected = typeof onRejected == 'function'? onRejected: err=>{throw err} let _promise = new MyPromise((fulfill, reject) => { // 实现then可能链式调用 返回一个本人的实例 if (this.status === FULFILLED) { setTimeout(() => { // 为了可能使_promise 实例化实现 所以应用setTimeout 等new完之后执行setTimeout try { let x = onFulfilled(this.value) // x 可能是一般值 有可能是promise // 判断x的值 => promise2的状态 resolvePromise(_promise, x, fulfill, reject) // fulfill(x) } catch (e) { reject(e) } }, 0) } if (this.status === REJECTED) { setTimeout(() => { try { let x = onRejected(this.reason) resolvePromise(_promise, x, fulfill, reject) } catch (e) { reject(e) } }, 0) } if (this.status == PENDING) { // 如果是异步 this.onFulfilledCallbacks.push(() => { setTimeout(() => { try { let x = onFulfilled(this.value) resolvePromise(_promise, x, fulfill, reject) } catch (e) { reject(e) } }, 0) }) this.onRejectedCallbacks.push(() => { setTimeout(() => { try { let x = onRejected(this.reason) resolvePromise(_promise, x, fulfill, reject) } catch (e) { reject(e) } }, 0) }) } }) return _promise }}// 提早对象MyPromise.defer = MyPromise.deferred = function(){ let dfd = {} dfd.promise = new MyPromise((resolve,reject)=>{ dfd.resolve = resolve dfd.reject = reject }) return dfd}module.exports = MyPromiselet p = new MyPromise((resolve, reject) => { resolve(100)})// let promise2 = p.then(data => {// return new MyPromise((resolve, reject) => {// setTimeout(() => {// reject('hello')// }, 0)// })// })// promise2.then(data => {// console.log('data:' + data)// }, err => {// console.log('err:' + err)// })// p.then().then().then().then(data=>{// console.log(data)// })// MyPromise.defer() 能够帮忙解决封装嵌套的问题let fs = require('fs')function read(url){ let dfd = MyPromise.defer() fs.readFile(url,'utf8',function(err,res){ if(err) dfd.reject(err) dfd.resolve(res) }) return dfd.promise}read('./name.txt').then(res=>{ console.log(res)})
实现promise.all() 办法(一种实现办法)
/** * promise.all() 全副 能够实现期待所有的异步执行完后 拿到对立的后果 * 解决异步并发 同步处理结果 */let MyPromise = require('./promise_then') // 本人封装的promise let fs = require('fs')function read(url) { let dfd = MyPromise.defer() fs.readFile(url, 'utf8', function (err, res) { if (err) dfd.reject(err) dfd.resolve(res) }) return dfd.promise}const isPromise = (val) => { if ((typeof val == 'object' && val !== null) || typeof val === 'function') { if (typeof val.then === 'function') { return true } } else { return false }}MyPromise.all = function (values) { return new MyPromise((resolve, reject) => { let arr = [] let index = 0 let processData = (key, value) => { arr[key] = value if (++index === values.length) { resolve(arr) } } for (let i = 0; i < values.length; i++) { let current = values[i] if (isPromise(current)) { current.then(res => { processData(i, res) }, reject) } else { processData(i, current) } } })}MyPromise.all([1, 2, 3, read('./name.txt'), 3, 4]).then(res => { console.log('all:' + res)})// all:1,2,3,'zhufeng',3,4
实现promise.all() 办法(第二种办法)
/** * promise.all() 全副 能够实现期待所有的异步执行完后 拿到对立的后果 * 解决异步并发 同步处理结果 */let MyPromise = require('./promise_then')let fs = require('fs')function read(url) { let dfd = MyPromise.defer() fs.readFile(url, 'utf8', function (err, res) { if (err) dfd.reject(err) dfd.resolve(res) }) return dfd.promise}// read('./name.txt').then(res=>{// console.log('read:'+res)// }) const isPromise = (val) => { if ((typeof val == 'object' && val !== null) || typeof val === 'function') { if (typeof val.then === 'function') { return true } } else { return false }}MyPromise.all = function (values) { return new MyPromise((resolve, reject) => { let arr = [] let index = 0 let processData = (key, value) => { arr[key] = value if (++index === values.length) { resolve(arr) } } for (let i = 0; i < values.length; i++) { let current = values[i] if (isPromise(current)) { current.then(res => { processData(i, res) }, reject) } else { processData(i, current) } } })}MyPromise.all([1, 2, 3, read('./name.txt'), 3, 4]).then(res => { console.log('all:' + res)})