1

I am working on a Node.js project that relies on the response of getObject from AWS. Currently, I can access the data I need and store it in a variable (header), but do not know how to make it available in the main function.

TileStreamerS3.prototype.Init = function(filepath, index, s3config){
   var retval = false; 
   AWS.config.update({accessKeyId: s3config.access_key, secretAccessKey: s3config.secret_key});
   var blc = new BlockLibraryConfigs(); 
   var awsConfig = blc.awsConfig; 
   AWS.config.update({region: awsConfig.region}); 

   var aws = new AWS.S3(); 
   var params = {
       Bucket: s3config.bucket, 
       Key: s3config.tile_directory + filepath, 
       Range: 'bytes=0-27'
   };



 aws.getObject(params, function(err, data){
       if(err == null){
            var header = bufferpack.unpack('<7I', data.Body);
            return header; 
       }
   }); 
}; 

How do I return the header variable? I saw a possible solution that used JQuery, but I'm on Windows and am having issues getting JQuery to work with Node. I don't want to have to go down that path if there's a better way to do it.

UPDATE: I know there are multiple questions regarding returning values from asynchronous functions. I think what's tripping me up is that aws.getObject() is a function that is taking in another function as a parameter. I want to return the header value from the function that is a parameter for the aws.getObject() function. Furthermore, I have no access to change the getObject() function.

9
  • jQuery works only on the web browser/front-end. NodeJS is the server/back-end. They cannot work together. Commented May 3, 2016 at 17:39
  • 1
    @BlazeSahlzen then why is there a npm package for it? npmjs.com/package/jQuery Commented May 3, 2016 at 17:40
  • It is there for you if you need to manipulate HTML data on the server-side. Commented May 3, 2016 at 17:44
  • @BlazeSahlzen Well I'm really just interested in using deferred: api.jquery.com/jquery.deferred Commented May 3, 2016 at 18:01
  • 1
    You can check out deferred, promise and async (this one's the most popular). Commented May 3, 2016 at 18:05

1 Answer 1

1

The first thing to understand about asynchronous programming is that you cannot actually return the result from your callback to your main function or anywhere else. Here's a tutorial on async coding to get you started.


As for your current situation, I would handle it using Async Waterfall. Async will force the otherwise asynchronous functions to behave synchronously by waiting for them to finish before calling the next function (with the output of the previous function as arguments to the next function).

Here is an example:

TileStreamerS3.prototype.Init = function(filepath, index, s3config, callback) {
// pass a callback function as a parameter

    var retval = false;
    AWS.config.update({
        accessKeyId: s3config.access_key,
        secretAccessKey: s3config.secret_key
    });
    var blc = new BlockLibraryConfigs();
    var awsConfig = blc.awsConfig;
    AWS.config.update({ region: awsConfig.region });

    var aws = new AWS.S3();
    var params = {
        Bucket: s3config.bucket,
        Key: s3config.tile_directory + filepath,
        Range: 'bytes=0-27'
    };

    async.waterfall([function(callback) {

        aws.getObject(params, function(err, data) {
            if (!err) {
                var header = bufferpack.unpack('<7I', data.Body);

                callback(null, header); // using this we are passing the control to the
                // next function in the array
            }
        });

    }, function(header, callback) { // this is the function which will be called 
        // synchronously from aws.getObject's callback

        // use the header value passed from the previous function
        // do the next bit of asynchronous computation

        callback(null, output_if_any); // call the next function or the final callback

    }], callback); // attach the callback function to the async.waterfall

    // due to the async nature of the code, anything written after the waterfall will
    // be executed before the above code! So if you try to set any variable within the 
    // async function's callback and console.log it here, you will get undefined.

};

What happens here is that using async.waterfall we can create a list of functions (each of which may contain asynchronous functions) to be called synchronously one-after-the-other. When all the functions have been executed, the final callback function at the end is called with the output results.

Now when you call the function TileStreamerS3.Init, you do it like this:

TileStreamerS3Object.Init(filepath, index, s3config, function(err, results) {

    if (err) {
        // handle the error
    } else {
        // do whatever you want with the results
        // and continue the processing
    }

});
Sign up to request clarification or add additional context in comments.

4 Comments

At the end of TileStreamerS3.prototype.Init I need to return a value based off of these results. How would I set TileStreamerS3.prototype.Init return's value?
I've updated the example showing how you can return your result from the function.
I'm sorry I made a mistake. As I said you cannot return the result from the function, you have to execute the remainder of your code in the callback function. I've updated the example.
Trying it out! Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.