Koa: Koa not waiting on await

Created on 12 May 2018  路  17Comments  路  Source: koajs/koa

Having a issue where Koa is returning early and not waiting for any of my await functions to finish.
Node: 9.10

//root.js
module.exports = async (ctx, next) => {
   const test = new Promise(function(resolve, reject) {
    setTimeout(() => {
      return resolve('word');
    }, 1000);
  });

  ctx.body = await test
}

//index.js
app.use(async ctx => {
  switch(ctx.path) {
    case '/':
      await root(ctx);
      break;
  }
})

This always throws a 404. How can I get Koa to wait for the await function to finish?

question

Most helpful comment

Ended up figuring it out. I was testing this code inside of a larger koa application. And in one of the other middleware files, I was not using await next(), when I updated my code everything worked properly. My bad.

All 17 comments

Figured it out, I need to be returning the middle into Koa itself and check the route in module itself because of the way i set it up. Sorry to bother.

Ran into another similar issue with await Promise.all

//root.js
  let feedPromises = feeds.map(feed => {
      return new Promise(function(resolve, reject) {
        setTimeout(() => {
          return resolve('word');
        }, 1000);
      });
  });

  let result;
  try {
    result = await Promise.all(feedPromises) // after this line koa returns
  } catch(e) {
    console.log(e);
  }

  ctx.body = result; // this is happening after the return

I'm going to to need a full example of what you're doing to pinpoint any issue. There's insufficient information for me to be helpful here. On a different note, general usage questions are better suited elsewhere and you might get help faster - unless you think this is a Koa bug in which case I'd ask you to provide a fully reproducible example for further investigation.

Sorry, provided a full example. I'm not sure if its a bug, the behavior doesn't seem like its inline with how the docs describe the behavior but I can definetly be wrong. Koa version 2.5.1

//index.js
const Koa = require('koa');
const app = new Koa();
const update = require('./routes/index.js');
app.use(index);
app.listen(3000, () => { console.log('listening on 3000') });
// routes/index.js
module.exports = async (ctx, next) => {
  let promise = () => {
    return new Promise(function(resolve, reject) {
      setTimeout(() => {
        return resolve('word');
      }, 10);
    });
  }

  result = await Promise.all([promise()]) 
 // result = await promise() //this and the above line are happening after koa has already returned 

  ctx.body = result;
}

The only thing I see is that you're assigning to result without defining it. In strict mode this causes a ReferenceError, not sure how it plays out in normal mode. Anyway, I can't recreate your issue because I'm getting expected results (i.e. word).

You require routes/index.js as update, but you app.use it as index.

Ended up figuring it out. I was testing this code inside of a larger koa application. And in one of the other middleware files, I was not using await next(), when I updated my code everything worked properly. My bad.

Hello , I have similar issue :

app.use(async (ctx, next) => {
    const req = ctx.req.req || ctx.req;
    ctx.mySelf = await new Promise((resolve, reject) => {
        // req.on('data', (buffer) => {
        //     const value = buffer.toString('utf-8')
        //     resolve(JSON.parse(value))
        // })
        setTimeout(() => {
            resolve('test')
        }, 1000)
    })
    console.log(ctx.mySelf)
    await next()
})
app.use(bodyParser());

It works , but If run the annotated code, the http request is always pending.
The console also has no output

interview.js

const interviewRouter = require('./routes/interview');
app.use(router.routes()).use(router.allowedMethods());
router.use('/interview', interviewRouter.routes(), interviewRouter.allowedMethods());
interviewRouter.post('/post', async (ctx) => {
    console.log(ctx.request.body)
    console.log(ctx.mySelf)
    ctx.body = {
        success: true
    }

})

Ohh. My fault... It doesn't matter of koa.

Hello guys,

How can i use await Promise.all for my function?
i have use kao v2.7 and when i call await Promise.all as my function it's return 404 every time how i can fix it... please help

Thanks.

@Cmdrobot you probably just missed to return. Remember that Promise.all also is a promise.

@Cmdrobot , you can simplify your code, and show it. It's better way for get answer.

async function generateVideoThumb(videoPath, savePath, imageSize) {
    return new Promise((resolve, reject) => {
        ffmpeg(videoPath).on('error', (err) => {
            reject(err);
            console.log('err:', err)
        }).on('end', function(){
            resolve()
            console.log('success')
        }).screenshots({
            timestamps: ['25%', '50%', '75%'],
            filename: `%b.jpg`,
            folder: `public/uploads/${savePath}/thumbnails`,
            size: `${imageSize.width}x${imageSize.height}`,
            count: 1
        });
    });
}

var upload = async function(ctx, next){
   const results = files.map(async file => {
        let filenames = file.name.split(".")
        let ext = filenames.length > 1 ? filenames[filenames.length - 1]:"jpg"
        var savePath = "files"
        if (file.type == "image/jpg" || file.type == "image/jpeg" || file.type == "image/png") {
            savePath = "images"
        }else if (file.type == "video/mp4" || file.type == "video/quicktime") {
            savePath = "videos"
        }
        let name = Math.random().toString().replace(".", "")
        let filename = `files-${name}.${ext}`
        let filePath = `./public/uploads/${savePath}/`+filename
        var imageSize = {width: 0, height: 0}
        if (file.type == "image/jpg" || file.type == "image/jpeg" || file.type == "image/png") {
            imageSize = await imageSizeWithPath(savePath, filename)
        }else if (file.type.match("video")){
            imageSize = {width: 320, height: 240}
            let videoPath = `public/uploads/${savePath}/${filename}`;
            await generateVideoThumb(videoPath, savePath, imageSize)
        }
        return {
            "content-type": file.type, 
            "url": "??????", 
            "width": imageSize.width || 0, 
            "height": imageSize.height || 0
        }
    })

    let output = await Promise.all(results) <----- this line is fine when i have log as console

    // after this line i have receive response code is 404
    ctx.status = 200;
    ctx.body = ctx.config.response(200, 'test', output)
    await next();
})

please help......thanks

router.get(`${BASE_URL}/testAsync`, async (ctx) => {
    ctx.response.body = await f1()
});

async function f1() {
    return new Promise((resolve, reject) => {
        let message = {
            greeting: "Hello",
            planet: "World"
        }
        setInterval(function(){ 
            resolve(message)
        }, 3000);

    })
}

And this function is same issue

This code works very well, and don't know what your question. @Cmdrobot

var app = new Koa();
var router = new Router();

function f1() {  // no need use async in here, async and await use by pairs
  return new Promise((resolve, reject) => {
      let message = {
          greeting: "Hello",
          planet: "World"
      }
      setTimeout(function(){  // why use setInterval?
          resolve(message)
      }, 3000);
  })
}

router.get('/test-async', async (ctx) => {
  ctx.response.body = await f1();
});

app
  .use(router.routes())
  .use(router.allowedMethods());

app.listen(3000);

Ended up figuring it out. I was testing this code inside of a larger koa application. And in one of the other middleware files, I was not using await next(), when I updated my code everything worked properly. My bad.

I spent many hours finding the issue and this made it clear ! thanks a lot @fedgrant

Ended up figuring it out. I was testing this code inside of a larger koa application. And in one of the other middleware files, I was not using await next(), when I updated my code everything worked properly. My bad.

You saved me, man. Thanks a lot @fedgrant

Was this page helpful?
0 / 5 - 0 ratings

Related issues

imkimchi picture imkimchi  路  4Comments

rowild picture rowild  路  4Comments

xinshouke picture xinshouke  路  4Comments

ilkkao picture ilkkao  路  4Comments

ElegantScripting picture ElegantScripting  路  5Comments