Support promises in middleware

Supports synchronous middleware that returns a promise. How should falsy errors be handled? Since falsy values can be used to reject a promise or thrown. Most code doesn't actually handle these cases, so maybe we just do what everyone else does and forward it on or we can switch in a custom error instance when the error is falsy (`next(err || new Error('...')`).