2

I want to resolve a promise and then render a view like so in Koa 2.

async function render(ctx, next) {
  // wait for some async action to finish
  await new Promise((resolve) => { 
   setTimeout(resolve, 5000)
  })
  // then, send response
  ctx.type = 'text/html'
  ctx.body = 'some response'
  await next()
}

However when I do this, the server does not send any response (browser keeps waiting for a response, and times out). What am I doing wrong?

Shubham Kanodia
  • 6,036
  • 3
  • 32
  • 46
  • how do you declare this function to be used by koa? `koa.use(render)` ? – Ovidiu Dolha Jan 09 '17 at 07:17
  • @OvidiuDolha Yes, i'm exporting this middleware and doing a `const app = new Koa(); app.use(render)` – Shubham Kanodia Jan 09 '17 at 07:26
  • just curios if you do `koa.use((ctx, next) => render(ctx, next))` same problem? – Ovidiu Dolha Jan 09 '17 at 07:36
  • nevermind, I just replicated your example on a brand simple koa seed (https://github.com/chentsulin/simple-koa2-example) and works perfectly... the problem must reside somewhere else. What other middleware do you have in the app? Also: how do you start the server? And what version of node are you using? – Ovidiu Dolha Jan 09 '17 at 07:49
  • @OvidiuDolha I too tried to use the simple-koa example you linked to. Adding a : await new Promise((resolve) => { setTimeout(resolve, 10000) }) to the router.js file causes immediate return i.e. for some reason, the await of 10 seconds does not occur – Shubham Kanodia Jan 09 '17 at 08:00
  • I'm on node v7.x and starting server using `app.listen(port)` to start the server. – Shubham Kanodia Jan 09 '17 at 08:03
  • Using the router is something else - i was talking about just a basic koa - i.e. removed router and other middleware and just add the app.use(render) in server.js works as expected... So in the end, you are using also koa-router in your app also an want to do the above code in a router function? Or you're just using koa and no other middleware? – Ovidiu Dolha Jan 09 '17 at 08:07
  • Unfortunately my setup is a little complex, where I'm transcompiling this middleware to es5 using webpack. I'm trying to reduce the variables and see if I can get a minimal subset. – Shubham Kanodia Jan 09 '17 at 08:22
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/132674/discussion-between-user3210476-and-ovidiu-dolha). – Shubham Kanodia Jan 09 '17 at 08:33

3 Answers3

9

I realize that I'm a couple months late here, but I stumbled upon the same issue just now and discovered that in order for a given middleware to be able to wait for async executions, all of the preceding middleware has to await next(), as opposed to just next(). Make sure to verify that, seems obvious in hindsight.

I hope this helps.

m-a-r-c-e-l-i-n-o
  • 2,622
  • 18
  • 26
1

So, I took your code and created a little app:

const Koa = require('koa');
const app = new Koa();

async function render(ctx, next) {
  // wait for some async action to finish
  await new Promise((resolve) => { 
   setTimeout(resolve, 5000)
  })
  // then, send response
  ctx.type = 'text/html'
  ctx.body = 'some response'
  await next()
}

app.use(render);

app.listen(3000);

This works out of the box this way ... no changes needed. So it seems, the way you "used" your render function was somehow not correct.

Sebastian Hildebrandt
  • 2,661
  • 1
  • 14
  • 20
0

The way I write middleware is pretty similar with @Sebastian:

const Koa = require('koa');
const app = new Koa();

const render = async(ctx, next) {
    // wait for some async action to finish
    await new Promise((resolve) => { 
        setTimeout(resolve, 5000)
    });
    // then, send response
    ctx.type = 'text/html';
    ctx.body = 'some response';

    await next();
}

app.use(render);
....

hope it helps you

Tony
  • 21
  • 2