归档
迅速理清promise运行机制与实际中的应用
利用Promise解决批量文件串行下载问题
不用promise.all只用promise做并行下载文件
手写Promise前必须知道的几个小例子【一】
手写Promise前必须知道的几个小例子【二】
手写Promise分步骤超详尽解答(超越PromiseA+标准)
接上篇
三、异步三次调用后执行
- 上一篇最后一个例子有个调用三次后执行的例子,那么我们可以改造一下这个函数,比如我们要做三个异步操作,需要获得三个对象然后合成一个对象,最后得到这个合成的对象。
- 思路是这样:我们进行异步操作调用完成之后,执行这个3次后调用函数,然后当所有的异步操作完成以后,就执行了3次调用,于是可以执行三次调用后的操作了。
const after = (times, fn) => {
return () => {
times--;
if (times === 0) {
fn()
}
}
}
const fn = () => {
console.log('111')
}
const myfunc = after(3, fn);
let f1 = () => {
setTimeout(() => {
myfunc();
}, 1000);
setTimeout(() => {
myfunc()
}, 1000);
setTimeout(() => {
myfunc()
}, 2000);
}
f1()
- 这个settimeout可以当作获取数据之类的异步操作,操作后执行myfunc,myfunc设置3次后运行fn,本质上其实是个同步操作,就是方法不运行,等执行完毕后满足条件运行。
四、发布订阅模式
- 这个例子比上面稍微复杂点,但本质和上面差不多。
let school= {};
const e = {
arr:[],
on(fn){
this.arr.push(fn)
},
emit(){
this.arr.forEach(fn => fn());
}
}
e.on(()=>{console.log('订阅1')});
e.on(()=>{
if(Object.keys(school).length===2){
console.log("收到所有数据")
}
});
setTimeout(() => {//做异步操作后获取数据data
let data=['mydata1','111'];
school[data[0]]=data[1];
e.emit()
}, 1000);
setTimeout(() => {
let data=['mydata2','222'];
school[data[0]]=data[1];
e.emit()
}, 1000);
订阅1
订阅1
收到所有数据
111
- 在对象里放个数组和2个方法,发布时候就是异步完成时候,订阅就是把需要干的活push到数组里,发布时候就调用订阅的方法。
- 就相当于点外卖,点外卖就是订阅,外卖送来要时间就是异步,外面小哥通知你去取就是调用你前面订阅外卖留的电话,我取了外卖就执行。
五、观察者模式
class Subject{
constructor(name){
this.name=name;
this.arr=[];
this.state='11111'
}
push(myobj){
this.arr.push(myobj)
}
setState(mystate){
this.state=mystate;
console.log('substate='+this.state)
this.arr.forEach(fn=>fn.update(mystate));
}
}
class Observer{
constructor(name){
this.name=name
}
update(mystate){
console.log(this.name+mystate)
}
}
let sub = new Subject('sub');
let ob1 = new Observer('ob1');
let ob2 = new Observer('ob2');
sub.push(ob1);
sub.push(ob2);
sub.setState('state22');
substate=state22
ob1state22
ob2state22
- 这个跟上面的也差不多意思,就是把对象写成一个类,然后也是搞个数组,有人要观察这个对象,就把他push到数组去,当对象状态改变,就会调用Push进去的所有人实例的方法,从而得知状态改变。
- 观察者模式包含发布订阅模式。