Can we 'wait' until a previous function is done?


#1

Hi guys,

So here’s the thing, I have a socket server which pushes data to my meteor backend, this data is a sequence of commands, needed to be executed the exact way as it came in.

I’ve seen some weird race conditions where the next command is being executed and the previous command is still doing it’s job.

I’ve made a simpler example showing my problem:

var i, iid;

i = 0;

iid = setInterval(Meteor.bindEnvironment(function() {
  var idx, lol;
  idx = ++i;
  log('interval test', idx);
  lol = DBObject.find().fetch();
  if (i > 100) {
    clearInterval(iid);
  }
  return log('interval test done', idx);
}), 100);

Where DBObject can be any object from mongodb that we can use to block the fiber.
My logs look typically like this:

~~~ snip ~~~
I20160602-02:33:49.933(2)? interval test 28
I20160602-02:33:50.280(2)? interval test done 27
I20160602-02:33:50.281(2)? interval test 29
I20160602-02:33:50.687(2)? interval test done 28
I20160602-02:33:50.692(2)? interval test 30
I20160602-02:33:51.050(2)? interval test done 29
I20160602-02:33:51.051(2)? interval test 31
I20160602-02:33:51.462(2)? interval test done 30
I20160602-02:33:51.467(2)? interval test 32
I20160602-02:33:51.818(2)? interval test done 31
I20160602-02:33:51.824(2)? interval test 33
I20160602-02:33:52.228(2)? interval test done 32
I20160602-02:33:52.235(2)? interval test 34
I20160602-02:33:52.591(2)? interval test done 33
I20160602-02:33:52.595(2)? interval test 35
I20160602-02:33:53.004(2)? interval test done 34
I20160602-02:33:53.007(2)? interval test 36
I20160602-02:33:53.357(2)? interval test done 35
I20160602-02:33:53.359(2)? interval test 37
I20160602-02:33:53.776(2)? interval test done 36
I20160602-02:33:53.779(2)? interval test 38
I20160602-02:33:54.117(2)? interval test done 37
I20160602-02:33:54.123(2)? interval test 39
I20160602-02:33:54.546(2)? interval test done 38
I20160602-02:33:54.547(2)? interval test 40
I20160602-02:33:54.905(2)? interval test done 39
I20160602-02:33:54.910(2)? interval test 41
I20160602-02:33:55.318(2)? interval test done 40
I20160602-02:33:55.321(2)? interval test 42
I20160602-02:33:55.659(2)? interval test done 41
I20160602-02:33:55.665(2)? interval test 43
I20160602-02:33:56.077(2)? interval test done 42
I20160602-02:33:56.082(2)? interval test 44
I20160602-02:33:56.435(2)? interval test done 43
I20160602-02:33:56.445(2)? interval test 45
I20160602-02:33:56.859(2)? interval test done 44
I20160602-02:33:56.861(2)? interval test 46

As you can see the done and test log gets further away from eachother.
What I want is that it becomes:

I20160602-02:33:49.933(2)? interval test 28
I20160602-02:33:50.280(2)? interval test done 28 
I20160602-02:33:50.281(2)? interval test 29
I20160602-02:33:50.687(2)? interval test done 29
I20160602-02:33:50.692(2)? interval test 30
I20160602-02:33:51.050(2)? interval test done 39

Etc etc.

I thought that if I wrap the whole function in 1 bindEnvironment it would actually do that, but that’s not the case, and I think I misunderstood that. Does anyone know how to accomplish this using fibers or anything else? Thanks!


#2

You can use promises, async and await

const read = stream => 
   new Promise ((resolve, reject) => {
     stream.on('data', d => ... )
     stream.on('close', () => resolve(r))
   })

(async function() {
    const data = await read (my_stream)
    console.log(data)
}())

The older style uses futures

const Future = require('fibers/future')
const future = new Future()
stream.on('data', d => { ... })
stream.on('close', () => future['return']())
future.wait()

#3

Thanks, we currently use the older meteor because it’s too much work to migrate this instant. I’ll try the future thing!