Open paulgrieselhuber opened 4 years ago
Same thing, I can't manage to respond immediately and continue function execution.
public static async orderFulfilled(ctx: Context, next) {
// need to immediately respond (in 5 seconds or so) otherwise they assume this request failed
ctx.status = 200;
ctx.body = 'ok';
await next();
// do the math.......
}
This doesn't work!
Here is the feedback I ended up getting: https://stackoverflow.com/a/60877855/1172519.
By the time I got a response I just ended up refactoring the "middleware" called by the server route as a sync (note: non-async) function (not middleware at all at this point due to the fact that a single sync method has to do all the work).
So I haven't tested the linked answer, but it appears to be a great way to establish general error handling for Koa.
However, I don't understand why this needs to be so hard.
Hey @paulisloud! Thanks for the tip! I finally achieved what I wanted without (adding additional) / (restructuring existing) middleware. Here's my solution for this:
// THE ROUTE METHOD, THE INITIAL ENTRYPOINT.
public static async orderFulfilled(ctx: Context, next) {
// need to immediately respond (in 5 seconds or so) otherwise they assume this request failed
ctx.status = 200;
ctx.body = 'ok';
await next();
// do the math.......
// calling timeDemandingTask WITHOUT AWAIT
timeDemandingTask();
}
// OUR TIME DEMANDING METHOD WE DON'T WANT TO WAIT
private static async timeDemandingTask(ctx: Context) {
// doing the math.......
await action_1();
await action_2();
await action_3();
await action_4();
// two minutes passed!
}
In the end it works as intended.
@AleksMeshkov yep, basically the same approach I ended up with. Cheers.
Hummm... This is not exactly Koa issue (IMO)!!
You can use worker_threads
to avoid blocking code and keep chaining flowing.
And your code will be consistent!
// thread-service.js
'use strict'
const {Worker, isMainThread} = require('worker_threads')
function runService(service, workerData) {
if (isMainThread === false) {
return
}
const worker = new Worker(service, {workerData})
worker.once('message', console.log)
worker.once('exit', code => {
worker.removeAllListeners()
worker.terminate()
if (code !== 0) {
new Error(`Worker stopped with exit code ${code}`)
}
})
}
module.exports = runService
// service.js
'use strict'
const {workerData, parentPort} = require('worker_threads')
// const db = require('./my-db')
;(async () => {
try {
// do your stuff with data
// const result = await db.save(workerData)
console.log('thread --->', workerData)
const result = Math.random()
parentPort.postMessage({result})
process.exit(0)
} catch (error) {
process.exit(1)
}
})()
// app.js
'use strict'
const {join} = require('path')
const Koa = require('koa')
const runService = require('./thread-service.js')
const app = new Koa()
app
.use(async (ctx, next) => {
const start = Date.now()
ctx.state.start = start
console.log('start --> goto b')
await next() // goto b
// a
const ms = Date.now() - start
ctx.set('X-Response-Time', ms)
console.log('a --> end')
})
.use(async (ctx, next) => {
// b
const {start} = ctx.state
// start thread and keep running
runService(join(__dirname, 'service.js'), {start})
console.log('b --> goto c')
await next() // goto c
// b2
// goto a
console.log('b2 --> goto a')
})
.use(ctx => {
// c
ctx.body = {ok: true}
// goto b2
console.log('c --> goto b2')
})
.on('error', console.error)
app.proxy = true
app.listen(3435, () => {
console.log('Running: http://[::1]:3435')
})
> node app.js
Running: http://[::1]:3435
start --> goto b
b --> goto c
c --> goto b2
b2 --> goto a
a --> end
thread ---> { start: 1587672397920 }
{ result: 0.5918108149573942 }
I am writing the middleware for API endpoints in my app that respond to webhooks from other applications, and am relatively new to Koa, so am not completely familiar with its patterns.
I would like to structure my middleware as follows:
However, this does not appear to be working, as an error in any of my async methods can cause the route to error out.
My goal is for this endpoint to always respond "yep, ok" (immediately), meaning it is simply up to the application to handle any error states.
I have researched this fairly well, and have come across this pattern:
However, this does not meet my needs as the middleware makes no use of
next
, so it is not really a useful pattern, so far as I can tell.Could someone tell me what I am overlooking? I wrote this question on StackOverflow several days ago, but getting nowhere.