koa-compose源码疑惑求助
发布于 7 年前 作者 huhu2356 3653 次浏览 来自 问答

提取了部分koa-compose代码,并作了修改,如下:

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

  listen() {
    const cb = this.compose(this.middleware);
    const x = cb();
    console.log(x);
  }

  use(fn) {
    this.middleware.push(fn);
  }

  compose(middleware) {
    return function () {
      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 (!fn) return Promise.resolve();
        try {
          return Promise.resolve(fn(function next() {
            return dispatch(i + 1);
          }));
        } catch (error) {
          return Promise.reject(error);
        }
      }
    };
  }
}

const ko = new koa();

ko.use(async next => {
  console.log(1);
  await next();
  console.log(5);
});

ko.listen();

output:

1
Promise { pending }
5

问题: 1、 为什么输出是1 promise { pending } 5 , 而不是1 5 promise 2、

          return Promise.resolve(fn(function next() {
            return dispatch(i + 1);
          }));

能不能改为

          return fn(function next() {
            return dispatch(i + 1);
          });

根据MDN : The Promise.resolve(value) method returns a Promise object that is resolved with the given value. if the value was a promise, that object becomes the result of the call to Promise.resolve; 那么既然这个fn是async函数,且async函数返回的是promise.resovle(),那岂不是可以去掉外面这一层Promise.resolve?

大佬们,need help help ~~~

4 回复

第一个问题

(async () => {
	await Promise.resolve(1)
	console.log('2')
})()
console.log('1')

如果你明白上面执行顺序就不会有疑问了, 有疑问看 async 实现以及知道 promise.then 函数是 异步执行的

第二个问题 是可以去掉的, 但 koa 源码是 fn(ctx).then().catch() 你想想你要是普通函数且不返回 next() 岂不是 boom 了…

@5196666qwe nice ! (๑•̀ㅂ•́) ✧ 我之前还以为async function会全部执行完再执行接下来的代码,没想到执行到await,可以先暂停返回, 自己还是too young too simple啊

This is how async functions are executed:

  1. The result of an async function is always a Promise p. That Promise is created when starting the execution of the async function.
  2. The body is executed. Execution may finish permanently via return or throw. Or it may finish temporarily via await; in which case execution will usually continue later on.
  3. The Promise p is returned.

sugar for

let data = await something();
// ... do something ...

is

something().then(data => {
	// ... do something ...
});

thank you ,也解决了我一个疑惑。@huhu2356

回到顶部