Start using async/await instead of promises and callbacks

https://atmospherejs.com/okgrow/promise

I thought I’d show another pattern we can use for promisifying things, in case anyone likes it better, with less nesting. My above example would become:

function callMeteorMethod(methodName, ...args) {
    let resolve, reject
    const promise = new Promise((a, b) => { resolve = a; reject = b })

    Meteor.call(methodName, ...args, (error, result) => {
        if (error) reject(error)
        else resolve(result)
    })

    return promise
}


async function main() {
    let result = await callMeteorMethod('foo', 1, 2, 3)
    console.log(result)
}

main()

IIRC, Promise.await and Promise.async were always available on the server.

Are await myFunction() and async function(){} now available on the client as well?

2 Likes

Yes, they are available on the client in Meteor 1.3+

1 Like

Try doing this to simplify it:

await Promise.denodeify(Meteor.call).call(Meteor, [your arguments here])

@corvid Yep, in Meteor 1.3, ES7 is available on both client and server (async functions, es6 modules, everything!).

4 Likes

If one of the promises I am awaiting throws an error, what will happen?

You can use try/catch!

try {
  await promise;
} catch (e) {
  ...
}
4 Likes

For what its worth, I find asyn/await the most natural pattern in dealing with async code and try/catch is already a uniform way of error handling.

5 Likes

Good stuff. This seems like the ideal way to write apps. Does anyone know of a good Meteor 1.3 React example app using async/await?

2 Likes

Not sure, but my understanding is that that error gets returned, not swallowed, but I think it’s up to you how you handle it.

Why are there not that many actual MeteorJS server side examples? Tried to use async and await and was wondering why results are not ordered as expected when I clicked on a button?

In my case the client/main.js:

Template.resultfromACS.events({
'click .get_id' (event, instance) {
      (async function () {
          var result1 = await Meteor.callPromise('getXml', '123456789=', 'seb'); 
          var result2 = await Meteor.callPromise('testFunction', result1);
       }());
   } 
});

in server/main.js:

Meteor.methods({

    getXml : async function (authorizationCode, username) {
        var url = "".concat("https://myHost/Rest/Identity/User/name/",username);
        var req = unirest("GET", url);
        req.headers({
        "content-type": "application/xml",
        "authorization": "".concat("Basic " ,authorizationCode)
        });
        await req.end(function (res) {
            if (res.error) throw new Error(res.error);         
            console.log('res.body is :', res.body);  
        });  
      }, 

      testFunction: async function (message) {
            console.log('Message is : ', message);
      }
});

Results in:

Message is : null
res.body is :<?xml version=“1.0” encoding=“UTF-8” standalone=“yes”?

Why is the second call to testFunction happening before the first call to getXml in this case, as I need to get result from first call and pass result1 into second method?


Would this be something better to use than async/await?

You can use them together with the promise mixin: https://atmospherejs.com/didericis/callpromise-mixin

So you could do:

await myMethod.callPromise(args);

And there’s a variety of other mixins as well! https://github.com/meteor/validated-method#community-mixins

thanks @sashko but how do you do it on the client? I’m getting stuck with this.

Async/Await is not supported on the meteor client, what can we use? Should I wrapasync the method?

I thought it was in Meteor 1.3, no?

1 Like

For people who are using Angular2-Metoer, I recommend using the built-in RxJS 5 (Observable) which is much more powerful!

Also, I posted it here about how to Subscribe data in Service using RxJS 5 which gives you a feel to start using the more powerful RxJS 5.

Hi, tried async with Meteor 1.3.3.1.
async function(...argus)=>{ // console.log("call"+id); return callMeteorMethod(name,...argus); }
Got an error:
Unexpected token (49:38)

What am I missing here? Any extra package to support this?

Thanks!

You’re using the arrow function syntax incorrectly by also typing the function keyword.