koa2 onion learning async

Because memory is so poor record, look at the source code more often see an idea, we koa2 use a lot es6 syntax, so it is to look at the source code to learn the grammar of it. After reading koa source, the core of an onion is called. So I would separate piece of code to simplify it down to look at their future suddenly remembered the time do not need to re-thinking the stroke.

  • First create a storage array middleware function
  • app.use middleware middleware into the array after the array is ready to start the service
  • Start callback service calls later, the middleware performs a recursive array middleware
  • After the execution returns Promise
  • I will take this order to function independent, and delete some of the original author to verify the code and the code console, assuming that each method are of app this instance, not to app. To write. Independent

middleware is to create an empty array on the instance,

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

        fn = convert(fn);
        //转换为async 函数
    }
    this.middleware.push(fn);
    return this;
    //返回新实例
}

复制代码

use approach is to put all the middleware in the middleware.

app.listen(3000, () => {

})


复制代码

After the array is ready to start the service

listen(...args) {

    const server = http.createServer(this.callback());
    return server.listen(...args);
}

复制代码

Create a node server calls the callback

 callback() {
    const fn = compose(this.middleware);

    if (!this.listeners('error').length) this.on('error', this.onerror);

    const handleRequest = (req, res) => {
        const ctx = this.createContext(req, res);
        return this.handleRequest(ctx, fn);
    };

    return handleRequest;
}
复制代码

callback method in the callback call to compose in

function compose (middleware) {
   //middleware 回调数组
    return function (context, next) {
        // last called middleware #
        let index = -1;
        return dispatch(0)
    }
    //返回一个prm状态
}
复制代码

Object returns a Promise to tell the result of the recursive call completion

function dispatch (i) {
    if (i <= index) return Promise.reject(new Error('next() called multiple times'))
    //判断如果i小于index直接返回错误
    index = i;
    let fn = middleware[i]; //取出数组中对应下标函数
    if (i === middleware.length) fn = next;
   
    if (!fn) return Promise.resolve();
    
    try {
        return Promise.resolve(fn(context, function next () {
            return dispatch(i + 1)
            //递归调用
        }))
    } catch (err) {
        return Promise.reject(err)
    }
}
因为是async  所以当 await 接收到返回的Promise结果以后就会逐个执行下去 ,
也就是说当async函数被逐个执行完毕以后返回一个Promise对象,那么就会从async函数最后一个await逐个向上返回调用,直到所有await执行完毕。
这就是洋葱式调用
 async function(){
  await fun1(async function() {
    await fun2(async function() {
      await fun3(async function(){
        return Promise.resolve();
      });
    });
  });
};
上一级的await一直在等待下一级的返回结果,所以逐级向下执行,在等到执行了Promise.resolve();有了返回结果以后再逐级向上返回
//
复制代码

Specific perform recursive call

 handleRequest(ctx, fnMiddleware) {
   
    return fnMiddleware(ctx).then(handleResponse).catch(onerror);
    //fnMiddleware 就是递归执行完毕以后返回prm对象接收一个函数
}
//callback里调永compose函数并将middleware传递过去

复制代码

// the last line of the object is actually returned fn

to sum up

koa idea actually is to use the new features es7 of async function of the new features, one by one waiting for the results of asynchronous, the result will be returned once the lower one by one to tell convey to the upper layer, the formation of onion-call, so to have to read the source code Learn async function, so in reading, they also reviewed the async function while learning, still very good. If you do not understand this function may get confused in a recursive call to the piece, I will not understand why will return results in the order after the recursive call is over. I think they get to know that even if they get to know koa2 core idea of ​​the other packages are some functions, you can take your time

app.use(async (ctx, next) => {
  console.log(1)
  //典型语法await在等待
  await next();
  console.log(2)
});
app.use(async (ctx, next) => {
  console.log(3)
  //典型语法await在等待
  await next();
  console.log(5)
});
返回结果 是 1,3,5,2,
这就是洋葱
这里附上经典的图吧

复制代码

Reproduced in: https: //juejin.im/post/5cf749fef265da1baa1e626d

Guess you like

Origin blog.csdn.net/weixin_33782386/article/details/91423472