Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using await in then callback - the keyword 'await' is reserved

In node.js, I have a database transaction, where I want to call an async method in then callback, but I get error message the keyword 'await' is reserved.

This is async saveImage function:

const saveImage = async (parsedLink) => {
  AWS.config.region = config.awsSettings.region;
  AWS.config.accessKeyId = config.awsSettings.accessKeyId;
  AWS.config.secretAccessKey = config.awsSettings.secretAccessKey;
  const bucket = new AWS.S3({
    params: {
      Bucket: config.awsSettings.images_bucket_name,
    },
  });

  const currentDateString = new Date().toISOString().replace(/\:|\./g, '-');
  const bodystream = new Buffer(parsedLink.imgUrl, 'binary');
  const imageUrlDomain = parseDomain(parsedLink.linkUrl).domain;

  const params = {
    Key: `${parsedLink.id}/${imageUrlDomain}_${currentDateString}${parsedLink.imgType}`,
    ContentType: parsedLink.imageMime,
    ContentEncoding: 'base64',
    Body: bodystream,
  };

  const resultPromise = await bucket.upload(params).promise();
  return resultPromise.Location;
};

If I want to use saveImage function, I get the error message.

module.exports.addTestObject = async (ctx) => {
  const testObj = ctx.request.body;
  try {
    switch (testObj.type) {
      case interestT.getType.link: {
        const knexTestObject = TestObject.knex();
        transaction(knexTestObject, trx =>
            TestObject.query(trx)
              .insert({
                interestDate: testObj.date,
              })
              .then(newInterest => {
                // save image
                if (parsedLink.saveImg) {
                  parsedLink.imgUrl = await saveImage(testObj);
                }

                newInterest.$relatedQuery('linkInterestsRel', trx).insert({
                  linkHeader: testObj.linkHeader,
                }),
              }
              ),
          )
          .then((linkInterest) => {
            console.log(linkInterest);
          })
          .catch((err) => {
            throw err;
          });
        break;
      }
      default:
        break;
    }
    ctx.response.body = interestObj;
  } catch (err) {
    const statusCode = err.status || 400;
    ctx.throw(statusCode, err.message);
  }
};
like image 200
Matt Avatar asked Jan 09 '18 16:01

Matt


People also ask

Can we use await with callback?

The await keyword is used in an async function to ensure that all promises returned in the async function are synchronized, ie. they wait for each other. Await eliminates the use of callbacks in . then() and .

Can we use await in then?

The await keyword is used to get a value from a function where you would normally use . then() . Instead of calling . then() after the asynchronous function, you would simply assign a variable to the result using await .

How do I fix unexpected reserved word await?

The "unexpected reserved word await" error occurs when the await keyword is used inside of a function that was not marked as async . To use the await keyword inside of a function, mark the directly enclosing function as async .

Is the await keyword blocking?

await doesn't block. It suspends the function execution thus allowing other code to run. Resuming after the awaited value is resolved. So, it's non-blocking.


1 Answers

Regular functions run synchronously till they return. Therefore you cannot use await inside them as you cannot wait for an asynchronous event in a synchronous way.

JavaScript also has async functions, which look like regular functions, but are conceptually quite different: They run synchronously till they reach an await, then they stop and continue once the awaited Promise resolves. As such they cannot return their result synchronously, instead they return a Promise which then resolves when the function finished execution.

Therefore you need to convert your function into an async function:

 async function getUsername() { // <-- async keyword here
    return (await getUser()).name; // <-- await can be used inside
 }

Now this does also work inside a .then callback:

 getUser().then(async function(user) {
    const friends = await getFriends(user);
    // ...
 })

But this somewhat mixes the abstraction async functions with their underlying primitive Promise. If you would just await the Promise instead of adding a .then callback, the code gets way more readable:

 (async function() {
    const user    = await getUser();
    const friends = await getFriends(user);
 })();

The concrete question could be rewritten as:

 const linkInterest = await transaction(knexTestObject, async trx => {
     const newInterest = await TestObject.query(trx)
          .insert({  interestDate: testObj.date,   });

     if (parsedLink.saveImg) {
       parsedLink.imgUrl = await saveImage(testObj);
     }

    await newInterest.$relatedQuery('linkInterestsRel', trx)
       .insert({  linkHeader: testObj.linkHeader, }),
});
like image 131
Jonas Wilms Avatar answered Oct 20 '22 14:10

Jonas Wilms