Correct usage of Meteor.wrapAsync()

I’m trying to wrap an asynchronous function and call it synchronously using Meteor.wrapAsync(). I’m trying to move from the below server-side asynchronous call (which works fine):

if (!err) {
	Meteor.call("ldapLogin", username, password, Meteor.user());
}

where ldapLogin is in another server-side js file:

Meteor.methods({
	ldapLogin: function (username, password, userObj) {
		processLdapLogin(username, password, userObj);
	}
})

to something like this:

if (!err) {
	Meteor.methods({
		'ldapLogin': function(username, password) {
			var syncFunc = Meteor.wrapAsync(processLdapLogin);
			var result = syncFunc(username, password, Meteor.user());

			console.log(result);
		}
	});
	Meteor.call('ldapLogin', username, password);
}

Currently, I receive the following error:

Exception while simulating the effect of invoking ‘ldapLogin’ ReferenceError: processLdapLogin is not defined
at Meteor.methods.ldapLogin (http://localhost:3000/app/lib/ldap_shared.js?58bd12e667036c31820329433dfd394838cb27d4:24:61)

1 Like

You have a few typos in your sample. The method you call should have a matching method name defined, and since you’re passing in parameters you need to receive them. For example if you have:

Meteor.call('ldapLogin', username, password);

you would then have something like the following defined:

Meteor.methods({
  'ldapLogin': function (username, password) {
    check(username, String);
    check(password, String);
    // Assuming "processLdapLogin" exists somewhere else ...
    var syncFunc = Meteor.wrapAsync(processLdapLogin); 
    var result = syncFunc(username, password);
    console.log(result);
  }
});
1 Like

I do have a processLdapLogin method in another js file which was being called fine using the async Meteor.call. After making your suggested changes, processLdapLogin is not being called when I try to step through. This is what my code looks like now:

if (!err) {
	Meteor.call('ldapLogin', username, password);

	Meteor.methods({
		'ldapLogin': function(username, password) {
			check(username, String);
			check(password, String);
			var syncFunc = Meteor.wrapAsync(processLdapLogin);
			var result = syncFunc(username, password, Meteor.user());

			console.log(result);
		}
	});
}

Meteor.methods are not hoisted, so cannot be called before they are referenced.

However, I’m a little unclear what you’re trying to achieve here, as the context (specifically the client/server context) is not shown.

My bad, I’ve moved the calling statement. The code block above is within a server-side method called from the client on a sign-in event (login form submit). The processLdapLogin method is also on the server, in another js file. After moving the calling statement, I encounter the following error:

Exception while simulating the effect of invoking ‘ldapLogin’ ReferenceError: processLdapLogin is not defined at Meteor.call.Meteor.loginWithLDAP.Meteor.methods.ldapLogin (http://localhost:3000/app/lib/ldap_shared.js?ba17f688f0145921080673b6763ac0110a0502a5:24:61)

However, the processLdapLogin method does exist and I can ctrl-click into it in my WebStorm IDE, so not sure what I’m doing wrong at this point.

Are you sure the method is only on the server? The reference to .../lib/... in the exception suggests that your client has the method defined as well - in which case, it’s trying to run it as a simulation (and failing because processLdapLogin is not available on the client). As a workaround, you could just wrap the offending code in a if (Meteor.isServer) block. Better, you should recheck the structure of your code to ensure the method is defined only on the server (in a server/ folder).

It will be worth looking through the Meteor Guide on Methods.

When you say “the method”, are you referring to processLdapLogin? This is in fact a server-only method in server/ldap.js. When I only had the asynchronous method call, it would actually call the following Meteor Method in server/ldap.js:

Meteor.methods({
	ldapLogin: function (username, password, userObj) {
		processLdapLogin(username, password, userObj);
	}
})

However, I’ve since commented out the above in server/ldap.js and call processLdapLogin in server/ldap.js directly using Meteor.wrapAsync(processLdapLogin). Is this incorrect?

No, I mean where you have defined Meteor.methods({...