Running code AFTER the response has been sent by Koa

亡梦爱人 提交于 2020-01-04 04:30:28

问题


To optimize the response delay, it is necessary to perform work after are response has been sent back to the client. However, the only way I can seem to get code to run after the response is sent is by using setTimeout. Is there a better way? Perhaps somewhere to plug in code after the response is sent, or somewhere to run code asynchronously?

Here's some code.

koa                  = require 'koa'
router               = require 'koa-router'

app = koa()

# routing
app.use router app

app
  .get '/mypath', (next) ->
    # ...
    console.log 'Sending response'

    yield next

    # send response???

    console.log 'Do some more work that the response shouldn\'t wait for'

回答1:


Do NOT call ctx.res.end(), it is hacky and circumvents koa's response/middleware mechanism, which means you might aswell just use express. Here is the proper solution, which I also posted to https://github.com/koajs/koa/issues/474#issuecomment-153394277

app.use(function *(next) {
  // execute next middleware
  yield next
  // note that this promise is NOT yielded so it doesn't delay the response
  // this means this middleware will return before the async operation is finished
  // because of that, you also will not get a 500 if an error occurs, so better log it manually.
  db.queryAsync('INSERT INTO bodies (?)', ['body']).catch(console.log)
})
app.use(function *() {
  this.body = 'Hello World'
})

No need for ctx.end()
So in short, do

function *process(next) {
  yield next;
  processData(this.request.body);
}

NOT

function *process(next) {
  yield next;
  yield processData(this.request.body);
}



回答2:


I have the same problem.

koa will end response only when all middleware finish(In application.js, respond is a response middleware, it end the response.)

app.callback = function(){
  var mw = [respond].concat(this.middleware);
  var gen = compose(mw);
  var fn = co.wrap(gen);
  var self = this;

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

  return function(req, res){
    res.statusCode = 404;
    var ctx = self.createContext(req, res);
    onFinished(res, ctx.onerror);
    fn.call(ctx).catch(ctx.onerror);
  }
};

But, we can make problem solved by calling response.end function which is node's api:

exports.endResponseEarly = function*(next){
    var res = this.res;
    var body = this.body;

    if(res && body){
        body = JSON.stringify(body);
        this.length = Buffer.byteLength(body);
        res.end(body);
    }

    yield* next;
};



回答3:


you can run code in async task by use setTimeout, just like:

 exports.invoke = function*() {
  setTimeout(function(){
    co(function*(){
      yield doSomeTask();
    });
  },100);
  this.body = 'ok';
};


来源:https://stackoverflow.com/questions/26516082/running-code-after-the-response-has-been-sent-by-koa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!