【前端笔记】js洋葱模型的实现
首先,什么是洋葱模型?
洋葱模型指的是方法的执行像洋葱一样,一层一层往里执行,直到中心点后,再一层一层往外出来。
如下图:
代码如下:
// 洋葱模型顾名思义,指的是方法的执行像洋葱一样,一层一层往里执行,直到中心点后,再一层一层往外出来。 const middleware = [];middleware.push(function (next) { console.log(1); next(); console.log(4);});middleware.push(function (next) { console.log(2); next(); console.log(5);});middleware.push(function (next) { console.log(3); next(); console.log(6);});function compose(middleware) { return function () { function dispatch(i) { const fn = middleware[i]; if (typeof fn === 'function') { i++; const next = function () { dispatch(i); }; fn(next); } } dispatch(0); }}// 调用compose(middleware)();
分析
compose必须返回的是一个函数,并且每次函数执行,都需要将下一个函数作为参数传给它,这样才能够让方法一层层的执行下去,直到最里面一层:
function compose(middleware) { return function(args){ dispatch(0); function dispatch(index){ const fn = middleware[index] || args; if(typeof fn !== "function") return; const next = ()=> dispatch(index+1); fn(next); } }};
异步函数也能的处理:
function asyncFn() { return new Promise((resolve, reject) => { setTimeout(() => { console.log("delay..."); resolve(); }, 1000); });}const fn1 = async (next) => { console.log(1) await next() console.log(2)}const fn2 = async (next) => { console.log(3) await asyncFn(); await next() console.log(4)}const fn3 = async (next) => { console.log(5) await next() console.log(6)};function compose(middleware) { return function (args) { dispatch(0); function dispatch(index) { const fn = middleware[index] || args; if (typeof fn !== "function") return Promise.resolve(); const next = () => dispatch(index + 1); // 给执行函数添加返回成功的Promise.resolve return Promise.resolve(fn(next)) } }};compose([fn1,fn2,fn3])();
Redux中间件
redux的中间件compose函数如下:
function compose(middleware) { return middleware.reduce((total, next) => (...args) => total(next(...args)));}
redux的中间件函数很不好理解,这里可以将它拆开进行分析:
const fn1 = (next) => { return ()=>{ console.log(1) next() console.log(2) }}const fn2 = (next) => { return ()=>{ console.log(3) next() console.log(4) }}const fn3 = (next) => { return ()=>{ console.log(5) next() console.log(6) }}const dispatch = compose([fn1,fn2,fn3])(()=> console.log("dispatch"));dispatch();
middleware经过reduce叠加,每次都将上一次的结果返回给下一个函数作参数:
// 第1次 reduce 的返回值,变成 total 传递到下一次 arg => fn1(() => fn2(arg)); // 第2次 reduce 的返回值,继续作为下一次的 total arg => (arg => fn1(() => fn2(arg)))(() => fn3(arg));
或者将compose转成比较好理解的函数迭代形式:
function compose(middleware) { return function(cb) { function dispatch(index){ const fn = middleware[index]; const next = ()=>dispatch(index+1); // 下一次的函数执行 // 如果不存在下一个函数了,拿到传参里面的函数执行,这里需要保证传参是一个函数,对应的是redux里面的dispatch参数 fn ? fn(next)() : cb() } // 最终返回一个函数 return ()=> dispatch(0); }};
over~~
头都大了
转载请注明——本文源自【玄北博客】www.xuanbeiweb.cn
免责声明:本站部分文章、数据、图片来自互联网,
如果侵犯了你的权益请来信告知我们删除,否则不承担相应法律责任。邮箱:xuanbei@xuanbeiweb.cn
下一篇:【前端笔记】简单的手风琴二级菜单