I am trying to wrapAsync an npm knox buffer put to s3.
The knox client.put function has its own listeners. eg on(‘response’)
How can i make this work synchronously in a meteor method?
I tried wrapping all the knox client functions - but that did not work eg :
var knoxS3Put = Meteor.wrapAsync(s3client.put, s3client); var knoxS3On = Meteor.wrapAsync(s3client.on, s3client); var knoxS3End = Meteor.wrapAsync(s3client.end, s3client);
Then I tried this :
var putToS3 = Meteor.wrapAsync(s3client.put, s3client);
var req = s3client.put('/quotes/'+newFileName, headers);
var putToS3_result = putToS3(newFileName, headers);
putToS3_result.on('response', Meteor.bindEnvironment(function(res) {
console.log(res)
return res;
}));
putToS3_result.on('error', Meteor.bindEnvironment(function(res) {
console.log(res)
}));
putToS3_result.end(content)
var req = s3client.put(newFileName, headers);
var on = Meteor.wrapAsync(req.on, req);
var on_result = on('response');
console.log(on_result);
var end = Meteor.wrapAsync(req.end, req);
var end_result = end(content)
console.log(end_result)
var syncFunc = function (fileName,headers,callback){
var result;
s3client.put(fileName, headers)
.on("response", function(res){ result = res;})
.end(content, callback(null,result));
}
var emitterFunction = Meteor.wrapAsync(syncFunc)
var emitterFunction_Result = emitterFunction(newFileName, headers, content);
console.log(emitterFunction_Result);
return emitterFunction_Result
Meteor.bindEnvironment ensures that the execution context of the callback runs in a Meteor fiber. That means that functions relying on a fiber (like MyCollection.insert()) will work. However, it does not provide a means towards sync-style programming. So, if you don’t need a fiber in your callback, there’s nothing to be gained from bindEnvironment.
Meteor.wrapAsync does let you use sync-style coding with asynchronous functions. Unfortunately for your use case, it’s written assuming npm’s de facto standard of a callback signature of (error, result). That means it won’t work as you want for these functions: your res will be treated as an error!
If you want sync-style coding here (i.e. avoiding nested callbacks) you could wrap the S3 functions in Promises and use async/await. Any fiber in the calling function’s body will be preserved should it be needed.
So: either forgo sync-style and use good old fashioned nested callbacks or wrap the functions in Promises and use async/await.
Sorry I should have been clearer - I am running this in a method - where the method is returning to the client the filepath of the uploaded file on s3.
That being the case - doesn’t that rule out nested callbacks?
It sounds like you’ll need to wrap in Promises … or you could wrap in your own fibers/futures … or perhaps wrap the s3 functions to use an (error, result) callback and then wrap those in Meteor.wrapAsync! The possibilities are almost endless .
I’d be inclined to give Promises and async/await a shot. That’s the most ecosystem-friendly approach right now.