Async await not working?


#1

Could someone share a light on why res2 and res3 are not passed within async and await properly?

import {Meteor} from 'meteor/meteor';


Meteor.methods({

    async testTopLevel() {
        const res1 = await Meteor.call('myFirstAsyncFunc', 1);      // x is : 7 
        const res2 = await Meteor.call('mySecondAsyncFunc', res1);  // y is : NaN
        const res3 = await console.log('Top results is :', res2);   // Top results is : { _45: 0, _81: 0, _65: null, _54: null }
        return res2;
    },

    async myFirstAsyncFunc (x)
    {
        var value = await Promise
            .resolve(x)
            .then(x => x * 2)
            .then(x=> x + 5)
            .then(x=> x * 2)
            .then(x=> x / 2)
            
        return value;
    },

    async mySecondAsyncFunc (y) {
        var value = await Promise
            .resolve(y)
            .then(y => y * 2)
            .then(y=> y + 5)
            .then(y=> y * 2)
            .then(y=> y / 2)
            
        return value;
    }
});

Meteor.startup(() => {

    Meteor.call('testTopLevel');

});

With output in this order:

I20160711-19:01:15.192(1)? x is : 7
I20160711-19:01:15.195(1)? Top results is : { _45: 0, _81: 0, _65: null, _54: null }
I20160711-19:01:15.196(1)? y is : NaN


#2

async functions return a promise.

async mySecondAsyncFunc (y) {
        var value = await Promise
            .resolve(y)
            .then(y => y * 2)
            .then(y=> y + 5)
            .then(y=> y * 2)
            .then(y=> y / 2)
            
        return value;
    }

This returns a promise on ‘value’, not value itself


#3

And methods don’t return values. They take a callback

Meteor.call('todos.updateText', {
  todoId: '12345',
  newText: 'This is a todo item.'
}, (err, res) => {
  if (err) {
    alert(err);
  } else {
    // success!
  }
});

#4
const res3 = await console.log('Top results is :', res2);   
// Top results is : { _45: 0, _81: 0, _65: null, _54: null }

There is nothing to wait for here.


#5

Just repeating (a simplified verion of) the example given here

import { Meteor } from 'meteor/meteor'

if (Meteor.isServer) Meteor.methods({ 'normal' : () => 1 })

if (Meteor.isClient)
{
  const call = method_name => new Promise ((resolve, reject) => {
    Meteor.call(method_name, (e, r) => resolve(r))
  })

  const f = async () => {
    const r = await call ('normal')
    console.log (r)
  }
  f ()
}

It prints 1


#6

Hi Diego,

Which Promise library are you using? The ecmascript, Bluebird or RSVP?

I thought the use of Promise and await async is so that you don’t have to use callbacks and avoid the righthand drift?


#7

“ecmascript”, which is installed with Meteor by default.

const r = await call ('normal')
console.log (r)

This code doesn’t have any callbacks and looks fairly sequential. The only problem with promises is they automatically chain : the second you use await the function where that code is used has to return a promise.

The only way out of the chain and call your code from a “normal” code is to call a function that discards it’s result. Which is why you have the code

  const f = async () => {   // <-- returns a promise
    const r = await call ('normal')
    console.log (r)
  }
  f () // <-- discards the promise 

That said, there is no miracle. Promises only give you a placeholder for your function to return something while the final value is computed. They don’t magically transform JavaScript into a concurrent programming language.