Loopback: Doc: how to use async functions

Created on 20 Mar 2018  路  5Comments  路  Source: strongloop/loopback

We should enhance our documentation to show how to use async functions in the following places:

  • as a custom remote method
  • as a remoting hook (beforeRemote, afterRemote, afterRemoteError)
  • as an operation hook

Related issues:

  • #3830
doc help wanted

Most helpful comment

Using async/await

Remote methods can also return a promise instead of using the callback parameter.

{% include code-caption.html content="/common/models/person.js" %}

module.exports = function(Person){

    Person.greet = async function(msg) {
        return 'Greetings...';
    }

    Person.remoteMethod('greet', {
          accepts: {arg: 'msg', type: 'string'},
          returns: {arg: 'greeting', type: 'string'}
    });
};

Using async/await

Operation hooks can also return a promise instead of calling the next parameter.

{% include code-caption.html content="/common/models/MyModel.js" %}

MyModel.observe('before save', async function(ctx) {
  //...
  return
});

Using async/await

Remote hooks can also return a promise instead of using the next parameter

_modelName_.beforeRemote( _methodName_, async function( ctx) {
    //...
});

This is what I propose for async examples to en/ lb3 and lb2 Remote-Methods.md, Remote-hooks and Operation-hooks.md.

All 5 comments

  • Is it sufficient to just put the promise versions of each function next to the callback one?
  • Should each example be followed by an async version or just the first of each page?
  • Should there be a warning against using the callback in each example or just the first example on the page?

Old

module.exports = function(Person){

    Person.greet = function(msg, cb) {
      cb(null, 'Greetings... ' + msg);
    }

    Person.remoteMethod('greet', {
          accepts: {arg: 'msg', type: 'string'},
          returns: {arg: 'greeting', type: 'string'}
    });
};

New

module.exports = function(Person){

    Person.greet = function(msg, cb) {
      cb(null, 'Greetings... ' + msg);
    }

    // Remote methods can return promises as well, 
    // but you cannot use the callback parameter.

    // Incorrect 
    Person.greet = async function(msg, cb) {
        cb(null, 'Greetings... ' + msg);
    }

    // Correct
    Person.greet = async function(msg) {
        return 'Greetings... ' + msg;
    }

    // Correct
    Person.greet = function(msg) {
        return new Promise((resolve, reject) => {
            resolve('Greetings... ' + msg);
        });
    }

    Person.remoteMethod('greet', {
          accepts: {arg: 'msg', type: 'string'},
          returns: {arg: 'greeting', type: 'string'}
    });
};

Is it sufficient to just put the promise versions of each function next to the callback one?

I think it's a good start! We can always refine the first version later, based on user feedback.

Should each example be followed by an async version or just the first of each page?

I think it's enough to show async function variant only in the first example on the page. Maybe create a new sub-section in each page that's dedicated to async function? It will make it easy to create URLs pointing exactly to the example using an async function.

Should there be a warning against using the callback in each example or just the first example on the page?

I think having a warning for each example would be excessive. My proposal:

  • in the first callback-based example, add a link to the example showing an async function
  • in the section about async functions, warn users to not call the callback

@Prancing-Pony @strongloop/lb-next-dev Thoughts?

Using async/await

Remote methods can also return a promise instead of using the callback parameter.

{% include code-caption.html content="/common/models/person.js" %}

module.exports = function(Person){

    Person.greet = async function(msg) {
        return 'Greetings...';
    }

    Person.remoteMethod('greet', {
          accepts: {arg: 'msg', type: 'string'},
          returns: {arg: 'greeting', type: 'string'}
    });
};

Using async/await

Operation hooks can also return a promise instead of calling the next parameter.

{% include code-caption.html content="/common/models/MyModel.js" %}

MyModel.observe('before save', async function(ctx) {
  //...
  return
});

Using async/await

Remote hooks can also return a promise instead of using the next parameter

_modelName_.beforeRemote( _methodName_, async function( ctx) {
    //...
});

This is what I propose for async examples to en/ lb3 and lb2 Remote-Methods.md, Remote-hooks and Operation-hooks.md.

The proposal looks reasonable. Could you please open a pull request where we can iron out any remaining details?

Closing it as resolved as PR https://github.com/strongloop/loopback.io/pull/688 has landed.
@marvinirwin, thanks again for your contribution.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

LightningK0ala picture LightningK0ala  路  47Comments

voitau picture voitau  路  75Comments

ritch picture ritch  路  55Comments

coodoo picture coodoo  路  100Comments

sam-artuso picture sam-artuso  路  40Comments