筹备工作
实现一个高阶函数
调用一个办法,在这个办法执行前先执行另一个办法
// 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 = MyPromise
let 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)
})
发表回复