Meteor Methods, return values via promise / async

I just wrote this up as a reply to another posters question without fully reading what they asked. I posted this reply, actually read the original post, then withdrew my reply, it was not applicable.
Not wanting to waist that effort, I post again here in a new thread. This is a topic I spent time learning recently, and thought other new users may value it. I am not asking for help, I hope I am preemptively offering it. If anyone has suggestions for improvements to this process I would love to hear them.

A simple example method:

Meteor.methods({
    'documents.insert': function documentsInsert(doc) {
        try {
            return Documents.insert({owner: this.userId, ...doc});
        } catch (exception) {
            throw new Meteor.Error('500', exception);
        }
    }
);

We can wrap this in a promise:

addDocument = (document) => {
    return new Promise((success, failure) => {
        Meteor.call('documents.insert', document, (error, documentId) => {
            if (error) {
                failure(error)
            }
            else {
                success(documentId)
            }
        });
    });
};

And we can call it like this:

addDocument(doc)
    .then(result => {
        console.log('Document Added: ',result);
    })
    .catch(error => {
        console.log('Error: ',error.reason);
    });

Or if we are in a function marked as async:

try {
    let result = await addDocument(doc);
    console.log('Document Added: ',result);
} catch (error) {
    console.log('Error: ',error.reason);
}

TT

5 Likes

You can also create a more generic version such as this callWithPromise funciton adapted from one courtesy of @robfallows.

const callWithPromise = (method, ...myParameters) => new Promise((resolve, reject) => {
    Meteor.call(method, ...myParameters, (err, res) => {
        if (err) reject(err);
        resolve(res);
    });
});
3 Likes

Thats a nice trick!

This inspires another JavaScript question; How does one attach a function like this to the Meteor namespace? Is it possible to make this a Meteor.callWithPromise() call? Would this be a good thing or a bad thing?
TT

1 Like

Sure, you can attach a callWithPromise method to the Meteor object. Whether it’s good or bad is a topic for debate. I personally try not to monkey patch others code, but some people don’t have an issue with it. In fact several packages on atmosphere such as grove:call-async already do this.

As far as how to do it you just assign the function to Meteor.callWithPromise.

Meteor.callWithPromise = (method, ...myParameters) => new Promise((resolve, reject) => {
    Meteor.call(method, ...myParameters, (err, res) => {
        if (err) reject(err);
        resolve(res);
    });
});
2 Likes

I posted a couple of blogs on this subject here and here.

There was a brief moment in time when we nearly got an official, automatically promisified Meteor.call. Currently, you’d need to do something along the lines of @copleykj’s suggestion.

2 Likes

@robfallows hope you are doing well :smiley: You were our mentor in the first batch of meteor university :smiley: . Last year I read this article you wrote and it seemed it was a bit tedious to implement async await in meteor. I tried my hands on express-apollo and used ES7 there and it was easy peasy to implement async await.

_myFunction = async () => {
    await console.log("works")
  }

So is there no easy way to get async await working in meteor yet ?

Hi @kaiyes - good to see you’re still around.

It’s just as easy as that.

async/await is no more difficult in Meteor than in any other modern JavaScript platform (maybe easier, because there’s much less faffing about with babel).

The articles were written to encourage developers to use modern syntax in Meteor, not to suggest that Meteor was in some special way trickier than expected :slight_smile:.

Having said that, there’s always room for improvement, and Meteor could really do with Promisified versions of Meteor.call, Meteor.apply and HTTP, at least (although they’re not difficult to add as a package). Perhaps it could also benefit from observables for reactive data.

However, playing catch-up applies to any established platform, and Meteor’s no different from any other in that regard. In the JavaScript world, platforms become established (read “contain legacy features”) very quickly. I think MDG’s doing an amazing job keeping Meteor relevant.

3 Likes

Hi @robfallows, glad to see you still working these forums! I read somewhere that Meteor will be getting “full” async/await support in 1.6.2? How will that change things?

1 Like

It already does have full async/await support on both the server and the client.

Perhaps you’re referring to the upcoming legacy browser targeting with a separated bundle so that we can get a slimmed down bundle for evegreen browsers, where async/await need not be implemented by unnecessary polyfills and transpilation.

Either case, it still does not mean any change for your code. Just makes your app run eariler and faster in modern browsers.

3 Likes

Hey @serkandurusoy, I was referring to the highlighted item, native async/await support, in Release 1.6.2:

I might have gotten this mixed up, I thought this meant we had “some” support, but there were gaps.

2 Likes

As @serkandurusoy said, that refers to this:

which is all about improved performance and bundle size by using native async/await.

4 Likes

Oh well, I thought there was something more to it for 1.6.2

Yup, that’s just about it, nothing to worry, nothing we’re missing, your standard javascript already fully applies to meteor’s build system while the build output is bound to improve as some of these tickets get resolved.

4 Likes

@serkandurusoy, my mentor in meteor university. How are you doing :smiley: ? and @aadams good to see you both here. ( I am the one who came after a while )

I was reading through The exact thread yesterday. So 1.6.2 is about legacy browser support and decreasing bundle size wherein we already have async-await working for some time now in meteor right ? Gotta open up a dummy meteor app and try

2 Likes

Oh hey I did not realize you were here, too. Nice surprize :slight_smile: Yup you should definitely catch up with what’s up here with Meteor, worth every second of it :wink:

1 Like

For 2 years:

3 Likes