从0到1,理解异步编程方案Promise(0)

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战javascript

  1. 理解什么是观察者模式
  2. 理解什么是发布订阅模式
  3. 理解什么是queueMicrotask()

本篇是Promise的基本前置知识,让手写一个Promise变的不在困难!!!,这是构建Promise的0前端

1. 观察者模式

1.1 基本理解

如图【观察者模式简图】:java

观察者模式简图.png 观察者模式讲述的是一对多的关系,简单的来讲就是一个对象的状态改变,触发不一样观察者动做回应,在《图解设计模式》一书当中,观察者模式就是作状态管理的一种设计模式

按图,咱们开始实现一个观察者模式浏览器

1.2 实现一个简单的观察者模式示例

  1. 建立一个Observer的类
  2. 建立一个被观察的类
  3. 被观察的类须要添加一个方法addObserver,来收集实例化的Observer
  4. 状态改变,通知实例化的Observer
// 建立一个Observer的类
class Observer {
	constructor(name,action = ()=>{}) {
	    this.name = name;
		this.action = action
	}
	runAction(state){
		this.action(state,this.name)
	}
}
// 建立一个被观察的类
class Subject {
	constructor(name,state) {
	    this.name = name;
		this.nowState = state;
		
		this.oldState = null;
		this.obseverList = new Set();
	}
	// 被观察的类须要添加一个方法addObserver,来收集实例化的Observer
	addObserve(obsever){
		this.obseverList.add(obsever)
		return this
	}
	// 状态改变,通知实例化的Observer
	notifyObserve(state){
		this.nowState = state;
		if(this.oldState!==this.nowState){
			for(let item of this.obseverList){
				item.runAction(this.nowState)
			}
			this.oldState = this.nowState
		}
		return this;
	}
}
const teacherA = new Observer('老师A',(state,name)=>{
	if(state === 'playing'){
		console.log( name+'发现你在玩,打电话找你家长' )
	}else if( state === 'studying'){
		console.log( name+'狠狠的表扬了你' )
	}
})

const teacherB = new Observer('老师B', (state,name)=>{
	if(state === 'playing'){
		console.log( name+'发现你在玩,罚站30分钟' )
	}
})

const deskmateA = new Observer('小明',(state,name)=>{
	if(state === 'eating'){
		console.log( name+'发现你在吃东西,所以他也开始吃' )
	}
})

const deskmateB = new Observer('小f',(state,name)=>{
	if(state === 'eating'){
		console.log( name+'发现你在吃东西,所以他也开始吃' )
	}
})
const You = new Subject('你','studying')
You.addObserve(deskmateA).addObserve(teacherA).addObserve(teacherB)
You.notifyObserve('playing')
You.notifyObserve('eating')
You.notifyObserve('studying')
复制代码

上面就是一个很是简单的观察者模式的实现。markdown

从中能够清楚的看到,Subject和各个Observer是松耦合关系。当state改变的时候,统一调取各个实例化ObserverrunAction去根据状态执行相应的逻辑就行了。异步

2 发布订阅模式

2.1 基本理解

发布订阅模式和观察者模式,大致上很像(好比尤大大就认为发布订阅模式和观察者模式就是同样的)。这里就不讨论大佬的思想,毕竟咱们都还不到掌控代码的程度。不过能够用观察者模式去类比发布订阅模式(发布订阅模式里的Publisher,就是观察者模式里的Subject,而Subscriber,就是Observer),只不过在发布订阅模式里面多了一个第三方Observer来转发,而不是Subscriber直接notify状态给Publisher函数

在前端中,其实浏览器监听事件就是一个典型的发布订阅模式。例如,document.addEventListener('click',()=>{}), document就是被监听也就是Publisher,'click'表明发布内容Subject,后面的函数的意思就是,订阅到这个事件是click那就执行这个函数。顺着这个来,就能出图了oop

如图【发布订阅模式】:post

发布订阅模式.png

2.2 实现一个简单的发布订阅模式示例

  1. 建立一个第三方观察者Observer
  2. 给第三方的观察者一个addEventListener来添加订阅某消息和订阅该消息的Subscriber行为,只是这里要注意的是,同一个消息不止一个Subscriber的行为能够定,继续添加Subscriber的行为
  3. 给第三方的观察者一个removeEventListener能够订阅解除,解除分两种一种是解除单个Subscriber对某个消息的订阅,和直接解除对某个消息的订阅
  4. 给第三方的观察者一个notify方法接受到Publisher的状态,触发Subscriber行为
class Observe {
	constructor() {
	    this.publisherMap = new Map();
	}
	/* * @param { String } type 订阅消息的类型 * @param { Function } actionfn 相应的Subscriber的动做,也是推送消息的目标的动做(Subscriber) **/
	addEventListener(type,actionfn){
		if( !actionfn ){
			console.error('绑定失败')
		}
		let actionfnList = new Set();
		if(this.publisherMap.has(type)){
			actionfnList = this.publisherMap.get(type)
		}
		actionfnList.add(actionfn)
		this.publisherMap.set(type,actionfnList)
	}
	// 取消订阅 Publisher
	removeEventListener(type,actionfn){
		if( this.publisherMap.has(type) && actionfn){
			const actionfnList = this.publisherMap.get(type)
			if(actionfnList.size){
				actionfnList.delete(actionfn)
			}else{
				this.publisherMap.delete(type)
			}
		}else if( this.publisherMap.has(type) && !actionfn){
			this.publisherMap.delete(type)
		}else{
			console.error('暂无这个消息队列')
		}
	}
	// 触发 Subscriber 的动做,也叫发布通知消息
	notify(type){
		if(this.publisherMap.has(type)){
			const actionfnList = this.publisherMap.get(type)
			for(let subscriberAction of actionfnList){
				subscriberAction(this);
			}
		}
	}
}
// 老师任命班长来监听你的状态
const monitor = new Observe()
const yourState = ['studying','eating']
const teacherAction = function(){
	console.log('要很很的表扬你')
}
const deskmeatAction = function(e){
	console.log('一块儿吃东西',e)
}
monitor.addEventListener(yourState[0],teacherAction)
monitor.addEventListener(yourState[0],()=>{
	console.log('给你一朵大大的红花')
})
monitor.addEventListener(yourState[1],deskmeatAction)
monitor.notify(yourState[0])
monitor.notify(yourState[1])
复制代码

从中能够发现,发布订阅模式里,发布者订阅者,不是松耦合,而是彻底解耦的。他们之间的联系由第三方的Observer来协调。从代码实现上来看,必要的构造函数只实现第三方的Observer便可

从中也能发现,发布订阅模式和观察者模式最大的区别在于,在发布订阅模式里,发布者,并不会直接通知订阅者,换句话说,发布者和订阅者,彼此互不相识。这也是彻底解耦的特色

3. 你所不知道的queueMicrotask()

JavaScript 中经过 queueMicrotask()使用微任务

这里不对微任务宏任务作深刻研究,只简单说明一下:任务能够当作一条一条的执行语句。,通常状况下是同步运行的,从上而下,当遇到异步的事件,就须要将异步事件推入事件循环队列,而事件循环队列有两种,一种是微任务循环队列,一种是宏任务循环队列。微任务先于宏任务执行。

简单使用以下:

console.log('a')
window.queueMicrotask(()=>{
	console.log('b')
})
console.log('c')
复制代码

掌握上面的内容,手写Promise将变的异常轻松。彻底不须要死记硬背了!!!

参考资料

  1. 观察者模式 vs 发布订阅模式h
  2. 图解设计模式
  3. queueMicrotask
相关文章
相关标签/搜索