Arash Saidi
Arash Saidi

Reputation: 2238

Synchronous methods in Meteor/Node

I have a function that spell checks a sentence:

let spellCheck = input => {
    let corrected = [];

    input.split(' ').map((word, index, array) => {
        G.dictionary.spellSuggestions(word, (err, correct, suggestion, origWord) => {
            correct ? corrected[index] = origWord : corrected[index] = suggestion[0];
        });
    });

    // terrible solution
    Meteor._sleepForMs(200);
    return ['SPELL', input, corrected];
};

The issue here is that the return statement happens before the corrected array is filled with the correct versions of the words that have a spelling error. My terrible solution has been to but a sleep function call before the return statement, but I can't rely on that.

I have looked into the option of using Meteor.wrapAsync(), but I don't know which method to use it on. I tried (naively) to make the spellCheck method async, but of course that did not work.

Is there a way to make the G.dictionary.spellSuggestions method itself synchronous?

Upvotes: 0

Views: 63

Answers (1)

ffxsam
ffxsam

Reputation: 27713

The official Meteor docs on Meteor.wrapAsync say:

Wrap a function that takes a callback function as its final parameter. The signature of the callback of the wrapped function should be function(error, result){}

That last part is key. The callback must have the exact signature function (error, result) {}. So what I would do is, make a wrapper for G.dictionary.spellSuggestions and then use Meteor.wrapAsync on that wrapper. E.g.:

function spellSuggestions(word, callback) {
  G.dictionary.spellSuggestions(word, (err, correct, suggestion, origWord) => {
    callback(err, { correct, suggestion, origWord });
  });
}

// This function is synchronous
const spellSuggestionsSync = Meteor.wrapAsync(spellSuggestions);

What I've essentially done here is packed the non-error results into a single object. If you were to call spellSuggestions (async) directly, it might look like this:

spellSuggestions(word, function (error, result) {
  if (!error) {
    console.log('Got results:', result.correct, result.suggestion, result.origWord);
  }
});

So now on the server side, you can use your function synchronously:

result = spellSuggestionsSync(word);

Upvotes: 2

Related Questions