In a series of Meteor.call()'s within each other, the original call is returning early

248 Views Asked by At

I've made a Meteor.Method (let's call it the fullFlow) which itself calls a bunch of Meteor methods. My goal is to have the subsequent methods called asynchronously since the subsequent method requires the res of the previous method to do its work.

The problem is, the callback from the fullFlow is getting returned after the first method in the series it runs since the first method gets a return value (and then passes it to the next method, etc).

This is my issue: I want the fullFlow method to wait until the last method in the series is completed and return it's value to the callback of the fullFlow.

I'm assuming my structure is all wrong and that's why this is happening. I'd appreciate it if someone could help me out and either fix my flow or explain what I'm missing so I can fix it!

Here's the code:

Meteor.methods({
  step1(params) {
    // work with params
    return stuff
  },

  step2(params) {
    // work with params
    return stuff
  },

  step3(params3) {
    // work with params
    return stuff
  },

  fullFlow(params) {
    Meteor.call('step1', params, function (err, res) {
      if (err) {
        throw new Meteor.Error(err);
      } else {
        Meteor.call('step2', res, function (err, res) {
          if (err) {
            throw new Meteor.Error(err);
          } else {
            Meteor.call('step3', res, function (err, res) {
              if (err) {
                throw new Meteor.Error(err);
              } else {
                return res;
              }
            })
          }
        })
      }
    })
  }
})

function fullFlow() {
  Meteor.call('fullFlow', params, function (err, res) {
    if (err) {
      console.log(err)
    } else {
      console.log(res)
    }
  })
}

fullFlow();

Now what's happening is that when step1's callback is called with the res, it's also calling the main callback of fullFlow. The weird part is the rest of the fullFlow method still continues to execute and functions as expected (ie it waits for the res of the previous method before going onto the next one and passes it through properly), but the general callback has been fired.

My problem is I need to have this fullFlow function running continuously. My goal was to wait for the function's callback to be called and then within that callback, call the function itself to start over. This will not work properly if the callback is called before the full series of methods are completed. Also I need the res from the last method called in the series to be returned to the fullFlow callback!

Any ideas?

1

There are 1 best solutions below

7
On

And just like that, I figured it out.

I wrapped everything inside the fullFlow method within a future. So the new syntax is:

var Future = Npm.require( 'fibers/future' );

fullFlow(params) {
  var future = new Future();

  Meteor.call('step1', params, function (err, res) {
    if (err) {
      throw new Meteor.Error(err);
    } else {
      Meteor.call('step2', res, function (err, res) {
        if (err) {
          throw new Meteor.Error(err);
        } else {
          Meteor.call('step3', res, function (err, res) {
            if (err) {
              throw new Meteor.Error(err);
            } else {
              return future.return(res);
            }
          })
        }
      })
    }
  })

  return future.wait();
}

Now the whole thing doesn't callback until the last method is done and it successfully returns the last res to the callback of fullFlow.

This works but I am still unsure if this is a hacky way to solve bad structure. I'd rather have proper structure. If someone can correct the overall structure please tell me!