Several implementations of compose in Koa and Reduce

The test code

const app = {
    middleWares: [].use(middleWarwe) {
        this.middleWares.push(middleWarwe)
    }
}
app.use((next) = > {
    console.log(1);
    next();
    console.log(2);
});
app.use((next) = > {
    console.log(3);
    next();
    console.log(4);
});

app.use((next) = > {
    console.log(5);
    next();
    console.log(6);
});
app.compose()
Copy the code

Koa synchronization is implemented

app.compose = function () {
    const middleWares = this.middleWares
    function dispatch(index) {
      if (index === middleWares.length) return;
      const middleWare = middleWares[index]
      return middleWare(() = > dispatch(index + 1))
    }
    dispatch(0)}Copy the code

Koa asynchronous implementation

app.compose = function () {
  const middleWares = this.middleWares
  function dispatch(index) {
    if (index === middleWares.length) return Promise.resolve();
    const middleWare = middleWares[index]
    return Promise.resolve(middleWare(() = > dispatch(index + 1)))
  }
  dispatch(0)}Copy the code

Reduce synchronization

app.compose = function(){
  const middleWares = this.middleWares
  return middleWares.reduceRight((a,b) = >() = >b(a),() = >{})()
}
Copy the code

The reduce of asynchronous

app.compose = function(){
  const middleWares = this.middleWares
  return Promise.resolve(middleWares.reduceRight((a,b) = >() = >Promise.resolve(b(a)),() = >Promise.resolve())())
}
Copy the code

New reduce synchronization

app.compose = function() {
  const middleWares = this.middleWares
  return middleWares.reduce((a, b) = > arg= > a(() = > b(arg)))(() = > {});
};
Copy the code

New reduce asynchronous

app.compose = function() {
  const middleWares = this.middleWares
  return Promise.resolve(middleWares.reduce((a, b) = > arg= > Promise.resolve(a(() = > b(arg))))(() = > Promise.resolve()));
};
Copy the code

async

app.compose = function(){
  const middleWares = this.middleWares
    return (async() = > {let next = () = >Promise.resolve()
      function createNext(middleWare,oldNext){
          return async() = > {return await middleWarwe(oldNext)
          }
      }
      for(let i=middleWarwes.length-1; i>=0; i--){ next = createNext(middleWarwes[i],next) } })() }Copy the code