0

With

fileA

userID = (userName) ->
  id = 0
  someAPI.getUser userName, (err, data, res) ->
    id = data.id if data
    console.log id # Outputs ID
    return
  id

console.log userID('someUsername') # Outputs 0

fileB

getUser: (username, callback) ->
  return api.get 'users/show', { 'username': username }, callback

how can I get console.log userID('someUsername') to output the ID as well, instead of 0? I.e. have it wait before returning id.

I have tried randomly wrapping stuff with Meteor.wrapAsync and Meteor.bindEnvironment but can't seem to get anywhere.

jiku
  • 283
  • 5
  • 16
  • 2
    Put it inside the callback to `someAPI.getUser`. – Pointy Oct 01 '14 at 15:22
  • 1
    Welcome to the marvelous world of asynchronous, you can't do that. See related http://stackoverflow.com/q/23667086/1331430 – Fabrício Matté Oct 01 '14 at 15:29
  • 2
    The answer as pertains to Meteor is to use Futures. Read [this](https://www.discovermeteor.com/patterns/5828399) and [this](https://gist.github.com/possibilities/3443021). – richsilv Oct 01 '14 at 15:41

2 Answers2

1

You can either do the work in the callback or control the flow with a promise or event emitter:

"use strict";

var Q = require('q');
var EventEmitter = require('events').EventEmitter;

// using a promise
var defer = Q.defer();

// using an emitter
var getUserID = new EventEmitter();

var id = 0;
getUser("somename", function (err, data, res) {
    if ( data )
        id = data.id;
    // simply do the work in the callback
    console.log("In callback: "+data.id);
    // this signals the 'then' success callback to execute
    defer.resolve(id);
    // this signals the .on('gotid' callback to execute
    getUserID.emit('gotid', id);
});

console.log("oops, this is async...: "+id);

defer.promise.then(
    function (id) {
        console.log("Through Promise: "+id);
    }
);

getUserID.on('gotid',
             function (id) {
                 console.log("Through emitter: "+id);
             }
            );

function getUser (username, callback) {
    setTimeout( function () {
        callback(null, { id : 1234 }, null);
    }, 100);
}
marneborn
  • 699
  • 3
  • 9
1

Thanks everyone. I found a solution using https://github.com/meteorhacks/meteor-async

getUserID = Async.wrap((username, callback) ->
  someAPI.getUser username, (err, data, res) ->
    callback err, data.id
)

console.log getUserID('someUsername')
jiku
  • 283
  • 5
  • 16