Getting wrapAsync to work on the client with Meteor.subscribe & Cordova Contacts


#1

Hi, I am looking for some help on waiting for two Asynchronous calls to complete on the client.

Background: I am looking to merge two list of users client side (on Cordova):

  1. A basic user list which I need to subscribe to on the server
  2. the Cordova contacts list which I need as per a find call, as per navigator.contacts.find(fields, onSuccess, onError, options);

I’d like to show these two lists merged into a single list. As Cordova is client-side only, this has to happen on the client.

I can do the Meteor.subscribe and wait for the onReady call back and then (nested in onReady) try and do the same for the navigator.contacts.find call but I am struggling with getting things to wait for them to complete before combining the lists for rendering.

My plan was to use Meteor.wrapAsync client side. My first try of trying to get the client to wait for the subscribe to complete does not seem to work. Here’s what I have on the client:

aFindAsyncContacts = function (query, callback){
    Meteor.subscribe('searchContacts', query, {
        onReady: function(){
            console.log("searchContacts READY !!!!!!!!!!");
            callback  && callback(null);
        },
        onStop: function(err){
            console.log("searchContacts Problem !!!!!!!!!!" + err);
            callback  && callback(err);
        }

    })

}

var waitForContacts = Meteor.wrapAsync(aFindAsyncContacts);
    var result = waitForContacts(query);
    console.log("result of async:" + result + " ABOUT TO RETURN CONTACTS")

Here’s the console out put that shows that the wrapAsync is not waiting for the subscribe to complete:

result of async:undefined ABOUT TO RETURN CONTACTS
selectize_helpers.js?d05c8975297110cd0ad43631f5bbeffce245ce1c:196 about to return []
selectize_helpers.js?d05c8975297110cd0ad43631f5bbeffce245ce1c:138 searchContacts READY !!!!!!!!!!

Any guidance appreciated


#2

I’ve never been entirely comfortable with wrapAsync() on the client. There are no fibers, so the callback has to be used. So I believe your example should look more like this:

aFindAsyncContacts = function (query, callback){
    Meteor.subscribe('searchContacts', query, {
        onReady: function(){
             callback  && callback(null);
        },
        onStop: function(err){
            console.log("searchContacts Problem !!!!!!!!!!" + err);
            callback  && callback(err);
        }

    })

}

var waitForContacts = Meteor.wrapAsync(aFindAsyncContacts);
waitForContacts(query, function() {
    console.log("searchContacts READY !!!!!!!!!!");
});

#3

@robfallows thanks for the response.

That shows the result in the callback, but them I am back to the starting gate, I think? Ie I’d like to call multiple async calls eg waitforContacts1 (ge from Meteor), waitForContacts2 (get from Cordova Contacts) etc etc… and then amalgamate the responses into a single array. If I am understanding this correctly, each of these would come back asynchronously at different times, so I won’t have time to amalgamate. Did I understand that correctly?

I guess a traditional Meteor approach would be don’t do this and just use reactivity to render the results as they become available in a collection/s. I just implemented this alternative and it will work, but then makes it difficult to use plugins like Selectize which expect a single result set.


#4

Take a look at this thread and this link in particular (note it uses the deprecated Meteor.http syntax - you should now use HTTP). However, it does show you how to kick off multiple, parallel asynchronous requests and get all the responses together when all calls have completed.


#5

You can use the async library or Promises to handle the flow of multiple asynchronous tasks.


#6

Thanks @robfallows @Sanjo I have ended up going the other route ( "don’t do this"I mentioned above), which I think will give me some better performance in the long run. So I may come back to this, if I hit a wall. Thanks again.