admin管理员组文章数量:1291047
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'
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'
Share
Improve this question
edited Dec 7, 2014 at 17:03
ProgramFOX
6,39011 gold badges48 silver badges54 bronze badges
asked Oct 22, 2014 at 20:02
GarrettGarrett
11.7k20 gold badges86 silver badges129 bronze badges
6
-
How do you send the request? There are usually
success
callbacks for this kind of thing – Brennan Commented Oct 22, 2014 at 20:04 -
2
Please show us your code. Usually, you'd just call
response.end()
to send/flush the response, and continue with your work. – Bergi Commented Oct 22, 2014 at 20:46 -
@Bergi
response.end()
isn't defined: github./koajs/koa/blob/master/docs/api/response.md. I usekoa-router
. I'll add some code. – Garrett Commented Oct 24, 2014 at 5:11 - Thanks. But isn't that Coffeescript, not ES6? – Bergi Commented Oct 24, 2014 at 5:21
-
Coffeescript in ES6. I just forgot to yield. Will fix. Also,
response.end()
isnt supported by koa: github./koajs/koa/blob/master/docs/api/context.md#ctxres – Garrett Commented Oct 24, 2014 at 5:21
4 Answers
Reset to default 8Do 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./koajs/koa/issues/474#issuement-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);
}
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 = pose(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;
};
If the generator solution doesn't work for you (e.g. you can't use generators, can't transition all of your app to using generators, you're running serverless, etc), you can call your task from a setImmediate
instead, e.g.
app.use((ctx, next) => {
await next();
setImmediate(() => {
void processData(ctx.request.body);
});
});
async function processData() {
// your async task here
}
setImmediate
just puts your function directly onto the event queue, which node will then fire as soon as it can (in most cases, this is effectively immediate). This allows the main middleware function to return as normal, as you're not blocking / interrupting the control flow at all.
I'd imagine this probably works a bit better on serverless too, because they typically handle the timer functions correctly, although I haven't personally tested it.
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';
};
本文标签: javascriptRunning code AFTER the response has been sent by KoaStack Overflow
版权声明:本文标题:javascript - Running code AFTER the response has been sent by Koa - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741518984a2383065.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论