在Koa发送响应后运行代码

时间:2014-10-22 20:02:09

标签: javascript optimization generator ecmascript-6 koa

要优化响应延迟,必须在将响应发送回客户端后执行工作。但是,在发送响应后,我似乎能够获得运行代码的唯一方法是使用setTimeout。有没有更好的办法?也许某个地方在发送响应后插入代码,或者在某处异步运行代码?

这里有一些代码。

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'

3 个答案:

答案 0 :(得分:9)

不要致电ctx.res.end(),它是hacky并绕过koa的响应/中间件机制,这意味着你也可以只使用express。 这是正确的解决方案,我也发布到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'
})

无需ctx.end()
所以简而言之,

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

不是

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

答案 1 :(得分:0)

我有同样的问题。

koa只有在所有中间件完成后才会结束响应(在application.js中,respond是响应中间件,它会结束响应。)

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);
  }
};

但是,我们可以通过调用response.end函数解决问题,该函数是节点的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;
};

答案 2 :(得分:-2)

您可以使用dim collection as new CollectionZone 'init collection collection = cType(collection.OrderBy(Function(obj) obj.debutXMetres).ToList(), CollectionZone) 在异步任务中运行代码,就像:

setTimeout