willconant / flow-js

Javascript Library for Multi-step Asynchronous Logic
MIT License
302 stars 15 forks source link

need to pass some additional data to this.MULTI() #9

Open scottsd opened 11 years ago

scottsd commented 11 years ago

When issuing multiple parallel requests and this.MULTI(), one can get the request results with argsArray. However, I need to pass some additional data, besides the data returned by the callbacks. Something like fs.rename("/tmp/c", "/tmp/3", this.MULTI(myData));

or fs.rename("/tmp/c", "/tmp/3", this.MULTI(), myData );

I'll use myData in the final function to figure out at what result I'm looking at.

akanieski commented 10 years ago

In this case I think I've often stored myData in a variable scope that is accessible to the entire flow.

bwin commented 10 years ago

Since it's still open I'll try to answer it.

@akanieski: @scottsd writes

I'll use myData in the final function to figure out at what result I'm looking at.

So I thinks he doesn't know from which call to fs.rename the error originated from. fs.rename("doesntexist", "mynewname", cb) for example throws an error like this (at least with node 0.10.25)

{ [Error: ENOENT, rename 'doesntexist']
  errno: 34,
  code: 'ENOENT',
  path: 'doesntexist' }

So in this case this would totally suffice to check the Error object, but maybe fs.rename was just a bad example?

So Scott, (at least with a recent version of node; haven't tested older ones) you don't need to do anything, because the info is in the error (if there are errors). If you just want to remember what files you renamed you can attach to this, see end of my comment.

Or maybe you want to wrap your rename calls in a wrapper. (But for fs.rename I don't think it's necessary.)

// give it a name you like
renameWithMoreInfoInCallback = function(fromName, toName, cb) {
    // closure to hold arguments
    cbWithInfos = (function(fromName, toName, cb) {
        // when `fs.rename` is done, it calls this function with `err` as param
        // but we have `fromName` and `toName` in our closure
        // so we call your original callback `cb` with our additional infos
        return function(err) { cb(err, fromName, toName); }
    })(fromName, toName, cb);

    // call the original `fs.rename` but with our special callback
    fs.rename(fromName, toName, cbWithInfos);
}

This way you can just use this.MULTI() as normal, because the callback now gives you the data you wanted. (You call renameWithMoreInfoInCallback instead of fs.rename with the same params.)

@akanieski another way to accomplish what you said is: You attach your data to this (e.g. this.myData = myData). All following functions (in the same flow) can then access this.myData.

bwin commented 10 years ago

You can also also pass an arg to this.MULTI that becomes the key of the result. (Sorry didn't knew that.)