發(fā)布-訂閱方式實(shí)現(xiàn)異步并發(fā)
通過發(fā)布/訂閱者模式實(shí)現(xiàn)異步并發(fā)
異步意味著我們不會像同步那樣順序或串行地獲取到程序每一步的執(zhí)行結(jié)果,什么時候得到結(jié)果是未知的
發(fā)布訂-閱者模式實(shí)現(xiàn)異步并發(fā)非常簡單亚茬,它的關(guān)鍵在于: 每次程序調(diào)用都會去執(zhí)行(即發(fā)布)已經(jīng)被訂閱過的所有方法,在訂閱的方法中去判斷是否滿足條件阅嘶,滿足條件則執(zhí)行接下來的其它操作..
實(shí)現(xiàn)流程
- 定義對象, 該對象具有訂閱方法、發(fā)布方法、用于存放訂閱方法的集合
let obj = {
// 用于存放所有訂閱的方法工扎,在每次發(fā)布的時候會挨個的執(zhí)行一次
funcArray: [],
// 用于訂閱,執(zhí)行它會把要訂閱的方法存放到方法集合中
on (func){
this.funcArray.push(func);
},
// 發(fā)布衔蹲,該方法會把訂閱的方法挨個的執(zhí)行一次肢娘,執(zhí)行的過程中不斷地去判斷是否滿足某個條件
fire (){
this.funcArray.forEach( func => func.apply(this, arguments));
}
};
- 定義用于監(jiān)測的對象
// 假定異步全部執(zhí)行完成后期望得到的結(jié)果是: myInfo = {age: 18, sex: 'man'}; 呈础,根據(jù)該條件定義對象
let myInfo = {};
// 判斷是否滿足的條件是: myInfo對象 既有age屬性,又有sex屬性;
let keys = Object.keys(myInfo);
if(keys.includes('age') && keys.includes('sex')){ // something.....}
- 訂閱方法
obj.on((key, data) => {
myInfo[key] = data;
let keys = Object.keys(myInfo);
if(keys.includes('age') && keys.includes('sex')){
console.log(myInfo);
}
});
- 異步執(zhí)行橱健,執(zhí)行的回調(diào)里面進(jìn)行發(fā)布
setTimeout(()=>{
obj.fire('age', 18);
}, 2000);
setTimeout(()=>{
obj.fire('sex', 'man');
}, 3000);
- 簡單化
// 訂閱的過程,實(shí)質(zhì)上就是把要執(zhí)行的方法存起來
let fn1 = function(){ console.log('fn1'); }
let fn2 = function(){ console.log('fn2'); }
let arr = [fn1, fn2];
// 發(fā)布實(shí)質(zhì)上就是把訂閱的方法挨個的執(zhí)行
arr.forEach(fn=>fn()); // 發(fā)布
- 完整代碼
可拷貝直接運(yùn)行
let obj = {
// 用于存放所有訂閱的方法而钞,在每次發(fā)布的時候會挨個的執(zhí)行一次
funcArray: [],
// 用于訂閱,執(zhí)行它會把要訂閱的方法存放到方法集合中
on (func){
this.funcArray.push(func);
},
// 發(fā)布拘荡,該方法會把訂閱的方法挨個的執(zhí)行一次臼节,執(zhí)行的過程中不斷地去判斷是否滿足某個條件
fire (){
this.funcArray.forEach( func => func.apply(this, arguments));
}
};
let myInfo = {};
obj.on((key, data) => {
myInfo[key] = data;
let keys = Object.keys(myInfo);
if(keys.includes('age') && keys.includes('sex')){
console.log('Success! coding...');
}
});
setTimeout(()=>{
obj.fire('age', 18);
}, 2000);
setTimeout(()=>{
obj.fire('sex', 'man');
}, 3000);