Coder Social home page Coder Social logo

compose's People

Contributors

autosponge avatar cesarandreu avatar chentsulin avatar dead-horse avatar dependabot[bot] avatar dirkdev98 avatar fl0w avatar hden avatar jeromew avatar jonathanong avatar niftylettuce avatar plasmapower avatar popomore avatar smmoosavi avatar stephenmathieson avatar tejasmanohar avatar tj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

compose's Issues

Unexpected identifier - `of`

This makes Node v4 a requirement which is not mentioned anywhere.

Shame to break Node 0.12.x support for such a minor syntax change, seeing as Koa@2 supports 0.12.x.

Consider: resolve next with ctx

As is, a middleware which acts on the return path will consistently redefine the handler for the call to next:

module.exports = (ctx, next) => {
  // down
  return next().then(() => {
     // up
  });
};

By resolving next with ctx, the handler could be hoisted:

const myMiddlewareUp = (ctx) => {
  // up
};

module.exports = (ctx, next) => {
  // down
  return next().then(myMiddlewareUp);
};

Debug uses non-standard `fn.name`.

Whilst fn.name will work across node environments, it appears to be non-standard.

However, the real problem is that anonymous middleware will not get a name in the compose stack, making debugging a little more difficult. This situation is difficult to avoid in middleware returned by koa-route for example (the name field is read only).

Example with koa-route:

app.use(route.get('/id/:id', middleware.getById));

becomes:

app.use(function* getById() {
    yield route.get('/id/:id', middleware.getById).apply(this, arguments);
});

Perhaps a better way would be to allow explicit naming of composed routes. i.e.:

compose([{ name: 'a', middleware: a }, ...]);

although that is a little bulky. I'd be happy to submit a PR if you have a preferred way of adding the name in.

Reorganize tests, and switch to Jest

Right now all of the tests are under one describe. I'm not sure we need to split them into more files, but multiple describe sections would certainly be nice.

npm update + koa dependecy

Hello,
could you please update koa-compose on npm + update the dependency in koa ? I need it for the _name / name order split before I can package my audit middleware.
Thanks

Strict mode compatibility issue.

When trying to run hello world with

node --harmony --use_strict app.js

I get

/home/user/node_modules/koa/node_modules/koa-compose/index.js:98
    console.log('  \033[1m%d | \033[0m<< \033[36m%s\033[0m', this._level, name
                                                    ^^
SyntaxError: Octal literals are not allowed in strict mode.

Can't use destructuring with async await.

Hi, i try write a api service for my project using a middlewares.
I write this middleware

export const globaHandler = async ({ response }, next) => {
  await next();
  const { errors } = response; // reference error response is null;
};

if i write like that

export const globaHandler = async (ctx, next) => {
  await next();
  const { errors } = ctx.response; // { object }
};

Why?

Part of my api service code

const doRequest = async (ctx, next) => {
  const response = await axios(ctx.options);
  ctx.response = response;
  await next();
};

const api = async (context, middleware) => {
  const middlewares = [
    apiMiddleware.globaHandler,
  ];

  if (middleware && Array.isArray(middleware)) {
    middlewares.push(...middleware);
  } else if (middleware) {
    middlewares.push(middleware);
  }

  middlewares.push(doRequest);

  const composition = compose(middlewares);

  const handleResponse = async (context) => {
    try {
      await composition(context);
    } catch (err) {
      console.error('Error at middleware composition', err);
    }

    return context.response;
  };


  return handleResponse(context);
};


/**
 * @param {makeRequestObject} { resource, params, query, data, middleware, cancel }
 * @returns {Promise}
 */

const makeRequest = function ({ resource, params, query, data, middleware }) {
  const { url, method, auth } = getResource(resource, params);
  const options = { 
    url,
    method,
    headers: {},
    params: query,
    meta: { auth },
  };
  const context = {
    options,
    response: null,
  };

  return api(context, middleware);
};

I found that some code in the source code like `Promise.reject(),Promise.resolve()` seems redundant

source code

  /**
   * @param {Object} context
   * @return {Promise}
   * @api public
   */

  return function (context, next) {
    // last called middleware #
    let index = -1
    return dispatch(0)
    function dispatch (i) {
      if (i <= index) return Promise.reject(new Error('next() called multiple times'))
      index = i
      let fn = middleware[i]
      if (i === middleware.length) fn = next
      if (!fn) return Promise.resolve()
      try {
        return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
      } catch (err) {
        return Promise.reject(err)
      }
    }
  }

This still works well

      return function (context, next) {
        // last called middleware #
        let index = -1
        return disctxtch(0)

        function disctxtch(i) {
            if (i <= index) throw 'next() called multiple times';
            index = i
            let fn = middleware[i]
            if (i === middleware.length) fn = next
            if (!fn) return ;
            try {
                return fn(context, disctxtch.bind(null, i + 1));
            } catch (err) {
                throw err
            }
        }
    }

For what purpose? Can you explain?

officially support mutating middleware

Because of #65, specifically lodash.flatten, compose() returns a generator based on a copy of the provided array from that point in time. Any changes made to this array subsequently will no longer be reflected in the returned middleware.

Previously, one could mutate the array after calling compose.

when i use koa-compose with koa-router, koa-router does not work.

app.js

const Koa = require('koa');
const app = new Koa();
const views = require('koa-views')(__dirname + '/views', {
    extension: 'pug'
});
const json = require('koa-json');
const onerror = require('koa-onerror');
const bodyparser = require('koa-bodyparser')({
    enableTypes:['json', 'form', 'text']
});
const logger = require('koa-logger');
const koa_static = require('koa-static')(__dirname + '/public')
const compose = require('koa-compose');

const index = require('./routes/index');
const users = require('./routes/users');

// error handler
onerror(app);

// composed middleware
const all = compose([
    bodyparser,
    json,
    logger,
    koa_static,
    views
]);

// routes
app.use(all);

// routes
app.use(index.routes(), index.allowedMethods());
app.use(users.routes(), users.allowedMethods());

module.exports = app;

Why use Promise.resolve() to wrap the execution results of each middleware?

In the following code, why use Promise.resolve() to wrap the execution results of each middleware?

try {
  return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
} 

I think it is enough to use Promise.resolve() to wrap dispatch(0) and return the rest of middleware execution results directly. Just like the following code:

return function (context, next) {
    // last called middleware #
    let index = -1
-   return dispatch(0)
+   return Promise.resolve(dispatch(0))
    function dispatch (i) {
      if (i <= index) return Promise.reject(new Error('next() called multiple times'))
      index = i
      let fn = middleware[i]
      if (i === middleware.length) fn = next
      if (!fn) return Promise.resolve()
      try {
-       return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
+       return fn(context, dispatch.bind(null, i + 1));
      } catch (err) {
        return Promise.reject(err)
      }
    }
  }

Could you help me to answer this question, please!

add compose.hook or similar

some API for extending externally, for example the new debug stuff I just added could live in a different module. I'd like to provide a nicer alternative that outputs HTML documents since the terminal quickly becomes a clusterfuck, especially with parallel requests

Control passed to handler before completing middleware chain

Hey, folks --

I feel like I must be doing something silly here, but I'm experiencing an issue where the middleware chain is not completely resolved before my code passes control to the final handler. Let me know if this is something I'm doing or an actual bug, thanks!

Setup:

  • Middleware #1 - immmediately calls next
  • Middleware #2 - immmediately calls next
  • Middleware #3 - Waits 2 seconds, then calls next
  • Handler - Print Finished when done

Expected Output:

Middleware #1: Triggered
Middleware #1: Next
Middleware #2: Triggered
Middleware #2: Next
Middleware #3: Triggered
Middleware #3: Next
Finished

Actual Output:

Middleware #1: Triggered
Middleware #1: Next
Middleware #2: Triggered
Middleware #2: Next
Middleware #3: Triggered
Finished
Middleware #3: Next

Code:

const compose = require('koa-compose');

/**
 * Simple App Structure.
 */
class App {

  constructor () {
    this.middleware = [];
  }

  use (fn) {
    if (typeof fn !== 'function') {
      throw new TypeError('middleware must be a function!');
    }

    this.middleware.push(fn);

    return this;
  }

  route (handler) {
    let fn = compose(this.middleware);
    return fn(this).then( () => this.handleRequest(handler) );
  }

  handleRequest (handler) {
    return handler();
  }
}

let app = new App();

/**
 * Setup Middleware
 */
app.use( (ctx, next) => {
  console.log("Middleware #1: Triggered");
  console.log("Middleware #1: Next");
  next();
});

app.use( (ctx, next) => {
  console.log("Middleware #2: Triggered");
  console.log("Middleware #2: Next");
  next();
});

app.use( (ctx, next) => {
  console.log("Middleware #3: Triggered");
  setTimeout( () => {
    console.log("Middleware #3: Next");
    next();
  }, 2000);
});

app.route(() => console.log("Finished") );

Abnormal middleware errors occurred and KOA could not catch error events. How about the following changes

function compose (middleware) {
if(!Array.isArray(middleware)) throw TypeError('Middleware stack must be an array!')
for (const fn of middleware) {
if(typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')
}

let index = -1 //

  /**
  • @param {Object} context

  • @return {Promise}

  • @api compose
    */
    return function (context, next) {
    return new Promise((resolve, reject) => {
    function dispatch (i) { //
    if (i <= index) {
    console.warn('[warn]next() called multiple times')
    return //reject(new Error('next() called multiple times'))
    }

           index=i
           let fn=middleware[i]
           if(i===middleware.length) fn=next //
           if(!fn) return resolve()
    
           try {
               return resolve(fn(context,dispatch.bind(null,i+1)))
           } catch (error) {
               return reject(error)
           }
    
       }
       dispatch(0)
    

    })

}

}

Behavior changes on 4.2.0

PR #96 introduced an operation reduce on each call of compose, which shallow copies the middleware array. Previously middlewares can be added after koa.listen, with the PR landed middlewares added by koa.use after koa.listen are no longer working. Furthermore, koa.middleware property no longer reflects the correct middleware array since compose fn holds its own copy of it.

Should this be considered as breaking changes/bugs?

I don’t understand how the error is thrown when I find that next is called repeatedly.

Hi, I am learning source code about koa.I'm sorry, my English is not good.

if (i <= index) return Promise.reject(new Error('next() called multiple times'))

I don’t understand how the error is thrown when I find that next is called repeatedly.

Below is my test code

const Koa = require('koa');

const app = new Koa();

app.use(
    async function (ctx, next) {
        try {
            await next();
        } catch (e) {
            console.log('catch error:', e.toString())
        }
    }
)

app.use(
    function (ctx, next) {
        console.log('m1');
        next();
        next();
    }
)

app.use(
    function (ctx, next) {
        console.log('m2');
        next();
        next();
    }
)

app.listen(3000);

The console will print a log when I trigger it

m1
m2
(node:15374) UnhandledPromiseRejectionWarning: Error: next() called multiple times
    at dispatch (/Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:36:45)
    at /Users/helloWorld/code/learn-koa/playground/main.js:27:9
    at dispatch (/Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:42:32)
    at /Users/helloWorld/code/learn-koa/playground/main.js:18:9
    at dispatch (/Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:42:32)
    at /Users/helloWorld/code/learn-koa/playground/main.js:8:19
    at dispatch (/Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:42:32)
    at /Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:34:12
    at Application.handleRequest (/Users/helloWorld/code/learn-koa/playground/node_modules/koa/lib/application.js:168:12)
    at Server.handleRequest (/Users/helloWorld/code/learn-koa/playground/node_modules/koa/lib/application.js:150:19)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:15374) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:15374) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
(node:15374) UnhandledPromiseRejectionWarning: Error: next() called multiple times
    at dispatch (/Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:36:45)
    at /Users/helloWorld/code/learn-koa/playground/main.js:19:9
    at dispatch (/Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:42:32)
    at /Users/helloWorld/code/learn-koa/playground/main.js:8:19
    at dispatch (/Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:42:32)
    at /Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:34:12
    at Application.handleRequest (/Users/helloWorld/code/learn-koa/playground/node_modules/koa/lib/application.js:168:12)
    at Server.handleRequest (/Users/helloWorld/code/learn-koa/playground/node_modules/koa/lib/application.js:150:19)
    at Server.emit (events.js:315:20)
    at parserOnIncoming (_http_server.js:874:12)
(node:15374) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
m1
m2
(node:15374) UnhandledPromiseRejectionWarning: Error: next() called multiple times
    at dispatch (/Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:36:45)
    at /Users/helloWorld/code/learn-koa/playground/main.js:27:9
    at dispatch (/Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:42:32)
    at /Users/helloWorld/code/learn-koa/playground/main.js:18:9
    at dispatch (/Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:42:32)
    at /Users/helloWorld/code/learn-koa/playground/main.js:8:19
    at dispatch (/Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:42:32)
    at /Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:34:12
    at Application.handleRequest (/Users/helloWorld/code/learn-koa/playground/node_modules/koa/lib/application.js:168:12)
    at Server.handleRequest (/Users/helloWorld/code/learn-koa/playground/node_modules/koa/lib/application.js:150:19)
(node:15374) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 3)
(node:15374) UnhandledPromiseRejectionWarning: Error: next() called multiple times
    at dispatch (/Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:36:45)
    at /Users/helloWorld/code/learn-koa/playground/main.js:19:9
    at dispatch (/Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:42:32)
    at /Users/helloWorld/code/learn-koa/playground/main.js:8:19
    at dispatch (/Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:42:32)
    at /Users/helloWorld/code/learn-koa/playground/node_modules/koa-compose/index.js:34:12
    at Application.handleRequest (/Users/helloWorld/code/learn-koa/playground/node_modules/koa/lib/application.js:168:12)
    at Server.handleRequest (/Users/helloWorld/code/learn-koa/playground/node_modules/koa/lib/application.js:150:19)
    at Server.emit (events.js:315:20)
    at parserOnIncoming (_http_server.js:874:12)
(node:15374) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 4)

If I change the function to asynchronous call, the error can be caught

const Koa = require('koa');

const app = new Koa();

app.use(
    async function (ctx, next) {
        try {
            await next();
        } catch (e) {
            console.log('catch error:', e.toString())
        }
    }
)

app.use(
    async function (ctx, next) {
        console.log('m1');
        await next();
        await next();
    }
)

app.use(
    async function (ctx, next) {
        console.log('m2');
        await next();
        await next();
    }
)

app.listen(3000);

Is it necessary to use asynchronous function?

Can't call method 'call' of undefined

When I first request the page I get the correct response, however the second request I get a 500 response.

app.use(function* (next) {
  // Array with middleware functions,
  // generated elsewhere, but on every request
  var mws = [];

  yield compose(mws);

  yield next;
});

Error stack:

TypeError: Cannot call method 'call' of undefined
at Object. (/Users/thomas/CloudStation/Dropbox/www/koa-router/node_modules/koa-compose/index.js:36:19)
at GeneratorFunctionPrototype.next (native)
at next (/Users/thomas/CloudStation/Dropbox/www/koa-router/node_modules/koa/node_modules/co/index.js:76:21)
at Object. (/Users/thomas/CloudStation/Dropbox/www/koa-router/node_modules/koa/node_modules/co/index.js:56:5)
at next (/Users/thomas/CloudStation/Dropbox/www/koa-router/node_modules/koa/node_modules/co/index.js:92:21)
at Object. (/Users/thomas/CloudStation/Dropbox/www/koa-router/node_modules/koa/node_modules/co/index.js:56:5)
at Server. (/Users/thomas/CloudStation/Dropbox/www/koa-router/node_modules/koa/lib/application.js:105:8)
at Server.EventEmitter.emit (events.js:101:17)
at HTTPParser.parserOnIncoming as onIncoming
at HTTPParser.parserOnHeadersComplete (_http_common.js:111:23)

Outdated yield tests

I found 2 outdated tests . They are on line 111 and line 139 respectively.
Should their names changed to awaiting something?

Also, one of the test ('should work when yielding at the end of the stack with yield*', line 139) does not make sense anymore. next is a function that returns a promise, not a promise. Await next will simply resolve the function itself without calling it. Should this test be removed?

[Question/Proposal] Sync/Async execution

Hi!

Thank you for koa ✌️

Background

I use [email protected] and koa@2.

Often my middleware do things like this:

app.use(function(ctx, next) {
   ctx.state.foo = 'bar' // <-- sync operation
   next()
})

I mean they perform synchronous operations.
At the moment koa-compose reduce operations of all types to asynchronous operations.

Proposal

We could perform more (non-blocking) work per one event cycle (v8) than we do now.

Explanation

Let me explain what I mean.

I took the example from official site and I tried realized my vision. I replaced Koa, Context & Compose so that they consider synchronous/asynchronous behavior.

It looks like after these modifications up/down stream behavior works as expected.
See code bellow

// node v7.6.0

// const Koa = require('koa')

function isAsyncFunction(any) {
  return Object.prototype.toString.call(any) === '[object AsyncFunction]'
}

class Koa {
  constructor() {
    this.middleware = []
  }
  use(fn) {
    this.middleware.push(fn)
  }
  dispatch() {
    let ctx = new Context()
    let iterator = this.middleware[Symbol.iterator]()
    let next = function () {
      let {done,value} = iterator.next()
      if (done) return
      if (isAsyncFunction(value)) {
        return value(ctx, next).catch(console.error) // TODO: handle errors
      } else {
        return value(ctx, next) // TODO: try {} ... catch(e) {}
      }
    }
    next()
  }
}

class Context {
  constructor() {
    this.method = 'EMULATION'
    this.url = '/'
    this.headers = {}
    this.body = null
  }
  set(key, value) {
    this.headers[key] = value
  }
}

let app = new Koa()

// ----------- EXAMPLE ---------------

// x-response-time
app.use(async function (ctx, next) {
  const start = new Date()
  console.log(1)
  await next()
  console.log(6)
  const ms = new Date() - start
  ctx.set('X-Response-Time', `${ms}ms`)
})
// logger
app.use(async function (ctx, next) {
  const start = new Date()
  console.log(2)
  await next()
  console.log(5)
  const ms = new Date() - start
  console.log(`${ctx.method} ${ctx.url} - ${ms}`)
})
// a sync function
app.use(function (ctx, next) {
  // a sync function
  console.log(3)
  next()
})
// response
app.use(ctx => {
  console.log(4)
  ctx.body = 'Hello World'
})

// ----------- \EXAMPLE ---------------

app.dispatch() // emulation

// app.listen(3000)
// curl localhost:3000

Caveats

app.use(function(ctx, next) {
  next().then() // <-- may not work. I did not tested this case.
})

Summarizing

I don't force use my implementation. It's only for example.
Key message is: if we would care about sync/async functions it probably may increase performance.

What do you think about it?

[Q&A] About Promise in the source code.

I am learning the source code of compose, and I found that for each callback it return a promise object.

I can not understand why should do that return a promise object. Could you please tell me the reason?

Thank you very mush. (^_^)v

License is not included

Since MIT license explicitly requires the inclusion of the license text, it is insufficient to merely state the license used as "MIT" in package.json.

Quote from the MIT license from https://mit-license.org/

... The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

Solution: create license.md or license.txt to include the content of the MIT license.

compose 3.1.0 may enter an infinite loop

Test case:

const compose = require("koa-compose");

compose([
  function A(ctx, next) {
    console.log("A called");
    return next();
  },
])({}, function B(ctx, next) {
  console.log("B called");
  return next(); // if call next function here, it will enter an infinite loop
}).then(() => console.log("done"), err => console.error(err));

Octal literals are not allowed in strict mode.

I happened to run an example with --strict-mode and noticed a syntax error, well I'm not sure if compose is even bothered about strict mode, the issue is with those console.log statements which is highlighting strings.

Multiple next with non async function

Hi,

I wrote test like below, it throw an error but it come like this

UnhandledPromiseRejectionWarning: Error: next() called multiple times

and the test failed. Is this expected?

  it(`should throw if next() is called multiple times in non async function`, async () => {
    const stack = [];

    stack.push((ctx, next) => {
      next();
      next();
    });

    expect.hasAssertions();

    try {
      await compose(stack)({});
    } catch (error) {
      expect(error).toBeInstanceOf(Error);
    }
  });

promote `yield* next` instead of `yield next`

it's faster: tj/co#43

at least it'll work with or without it. it's an easy win. testing koa's benchmark, here's loa without yield*:

screen shot 2013-11-09 at 2 36 29 pm

with yield*:

screen shot 2013-11-09 at 2 36 57 pm

only problem is that next() should always return a generator. that's an easy fix.

support variadic usage (rather than requiring an array)

this is just my ocd, but imo the latter looks much nicer:

app.use(route.get('/foo', compose([ middleware1, middleware2, routeHandler ])))

vs

app.use(route.get('/foo', compose(middleware1, middleware2, routeHandler)))

would you take a pr implementing this in a backward compatible way?

/cc @jonathanong

I can't catch the error ~

const compose = require('koa-compose');

const middleware = [
    function(ctx,next){
        ctx.step1 = true;
        next();
    },
    function(ctx,next){
        ctx.step2 = true;
        next();
    },
    function(ctx,next){
        ctx.step3 = true;
        a = b;
        next();
    }
];

const ctx = {};

compose(middleware)(ctx).then(console.log).catch(console.error);

I can't catch the error ~

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.