jeudi 18 février 2021

understand `use`/stack creation, middleware pattern

Im trying to understand how the code below works.

class Middleware {

  constructor(obj) {

      obj = obj || this;

      Object.defineProperty(this, "__obj", {
          value: obj
      });

      Object.defineProperty(this, "start", {
          value: (...args) => {     
              args[args.length - 1].apply(obj, args.slice(0, -1));
          },
          writable: true
      });

  };

  use(fn) {
    this.start = (stack => {
        return (...args) => { 
          stack(...args.slice(0, -1), () => {
            fn.call(this.__obj, ...args.slice(0, -1), args[args.length - 1].bind(this.__obj, ...args.slice(0, -1)));
        });
      }
    })(this.start);

  };

};


// EXAMPLE
const middleware = new Middleware();

middleware.use((date, {data}, next) => {
    console.log("use #1", date);
    setTimeout(next, 1000);
});

middleware.use((date, {data}, next) => {
    console.log("use #2", date);
    next(new Error("TEST"));
});

middleware.use((date, {data}, next) => {
    console.log("use #3", date);
    setTimeout(next, 1000); 
});


middleware.start(Date.now(), {
    data: true
}, (err) => {
    console.log("final", err)
});

What drives me crazy is the use function that "override" the start function and create so a callback stack. Can someone explain how this works?

I found the code on github: https://gist.github.com/aronanda/d31bb47918145a5aace6005f172e035d

I want to create a "abort" mechanism, that when you pass a error object to the next function, it jumps straight to the "final" callback you pass to the start method, with the error as parameter.

But for that i need to understand what is going on inside the use function.

Aucun commentaire:

Enregistrer un commentaire