#52 中间件模式


  • 0
    管理员

    改好之后想整理一下,然后发现我已经不认识这个代码了。

    const app = {
        //已注册的函数的指针链
        _fn: null,
    
        callback (ctx) {
          console.log(ctx)
        },
    
        // 注册中间件
        // 中间件的功能是把注册的函数添加到指针链末尾
        use(fn) {
            // 第一次注册
            if (!this._fn) {
                this._fn = fn;
                return;
            }
            let current = this._fn;
            while (current.next) {
                current = current.next;
            }
            //在指针链末尾添加注册的函数
            current.next = fn;
        },
    
        go(obj) {
            if(this._fn == null) {
              this.callback(obj)
              return
            }
            const nextFn = (m) => {
                return () => {
                    if (m.next) {
                        m.next(obj, nextFn(m.next));
                    }
                    else {
                      this.callback(obj)
                    }
                };
            }
            //神递归
            this._fn(obj, nextFn(this._fn));           
        }
    }
    

    我是谁,从哪来 要到哪去

    @ackerMan 还是这位老铁的思想好

    const app = {
      fns: [],
      callback (ctx) {
        console.log(ctx)
      },
      use (fn) {
        this.fns.push(fn)
      },
      go (ctx) {
        let index = 0;
        const next = () => {
          index ++;
        }
        this.fns.map((fn, i) => {
        	if(index == i) fn(ctx, next)
        });
        index === this.fns.length && this.callback(ctx);
      }
    }
    

  • 0
    administrators

    @陈小俊 可以想想有没有别的招数。更简单的方法。


  • 0

    @胡子大哈

    请问,啥叫 第二次 app.go 的时候 app.callback 没有被正确调用


  • 0
    administrators

    @Sunjourney 测试用里是不会 await 你的 go 的,所以你的 callback 会在测试用例之后调用,所以不会监测到。

    这里用同步就好了,题目没有要求异步。


  • 0

    @胡子大哈 3Q,我改改


  • 0

    @胡子大哈 咋感觉通过的代码只能支持同步呢,真实的实现也是这样子的嘛?


  • 1
    administrators

    @Sunjourney 有同步有异步,Redux 这类是应该是同步的。Koa 异步的,异步的可以搞个 (二)。


  • 3

    写的好复杂的样子。。明明一个reduce就能解决问题的

    const app = {
      callback (ctx) {
        console.log(ctx)
      },
      
      use (fn) {
        app.middleware = app.middleware || []
        app.middleware.push(fn)
      },
      
      go (ctx) {
        app.middleware = app.middleware || []
        app.middleware.reverse().reduce((p, c) => () => c(ctx, p), () => app.callback(ctx))()
      }
    }
    

  • 1
    administrators

    @CodeHz 你改成 reduceRight 连 reverse 都省了


  • -1

    @胡子大哈 我习惯reverse()+reduce()。因为这样看起来比较统一(都是小写字母)。。


  • 0

    const app = {
      callback (ctx) {
        console.log(ctx)
      },
    
      use (fn) {
        app.middlewares = (app.middlewares || []).concat(fn)
      },
    
      go (ctx) {
        let index = 0
        this.use(this.callback)
    
        const next = () => {
          if (index < app.middlewares.length) {
            app.middlewares[index++](ctx, next)
          }
        }
    
        next()
      }
    }
    

    -> 数据经过中间件以后并不正确,中间件也许没有被正确调用

    请问,这样的写法报错的原因是什么?


  • 0
    administrators

    @Sunjourney 穿插着 go 和 use 来使用看看,应该是这个问题。


  • 0

    @ScriptOJ 确实,但是中间件应该具有这种功能吗?写测试的时候基于什么样的考虑要写这个测试呢


  • 0
    administrators

    @Sunjourney 运行阶段强插中间件的情况比较少见,但也不是不可能;但中间件的 go 多次调用几乎肯定出现,例如 koa 中间件,每一次请求过来都相当于调用了一次 go。你这里的 go 每次都 use 一下 callback 估计不大妥。


  • 1

    const app = {
      k:[],
      callback (ctx) {
        console.log(ctx)
      },
      
      use (fn) {
        this.k.unshift(fn);
      },
      
      go (ctx) {
        this.k.reduce((f,n)=>ctx=>{n(ctx,()=>f(ctx));},this.callback)(ctx);
      }
    }
    

  • 0

    @CodeHz 那为啥不用unshift+reduce呢


  • 0

    @CodeHz
    请问一下,reduce中的第二个参数可以为函数?


  • 0

    const app = {
      q:[],
      flag:true,
      ctx:{},
      callback (ctx) {
        console.log(ctx)
      },
      
      use (fn) {
        let next = ()=> this.flag = true;
        this.q.push(()=>{fn(this.ctx,next)});
      },
      
      go (ctx) {
        this.ctx = ctx;
        let q = this.q;
        console.log(q);
        for(let i = 0,len = q.length;i<len;i++){
          if(this.flag){
            this.flag = false;
            q[i]();
          }else{
            break;
          }
        }
        if(this.flag){
          this.callback(this.ctx);
        }
      }
    }

  • 0

    const app = {
      fns: [],
      callback (ctx) {
        console.log(ctx)
      },
      use (fn) {
        this.fns.push(fn)
      },
      go (ctx) {
        let nexts = []
        let idx = 0
        this.fns.forEach((fn, index) => {
          nexts[index] = () => { idx++ }
          if (idx === index) fn(ctx, nexts[index])
        })
        if(this.fns.length === idx) this.callback(ctx)
      }
    }
    

  • 0

    var app = {
      middlewares:[],
      callback (ctx) {
        console.log(ctx)
      },
      
      use (fn) {
        /* TODO */
        this.middlewares.push(fn);
      },
      
      go (ctx) {
        /* TODO */
        var flag;
        function next(){
          flag = true;
        }
        
        this.middlewares.push(this.callback);
        this.middlewares.every(function(fn){
          flag = false;
          fn(ctx, next);
          return flag
        });
      }
    }
    

    请教各位大神,这种写法下哪种用例过不去呢?


登录后回复
 

与 ScriptOJ 的连接断开,我们正在尝试重连,请耐心等待