0

I am in the process of writing an internal NPM module for my company so that applications can interact with a hardware device we have, which we already have a library written for communicating with it. The problem is, one method I am trying to write needs to execute asynchronously. I want the function to send a command to read from the device, wait for it to return (the device library handles this), and then I parse the results. What I am hoping for is for other developers to be able to call exports.getResolution() to get the values. Here is a snippet of my file with the relevant parts:

var async = require('async');

exports.getResolution = async.series([
    function(callback) {
    board.sendAndReceive(bufferlib.generateBuffer("read", "0x00001220", "0x00000004"), (function(received) {
            var hex = bufferlib.sortReceivedHex(received);
            var status = parseInt('0x' + hex.substring(0, 1), 16);
            var verticalResolution = parseInt('0x' + hex.substring(1, 4), 16);
            var horizontalResolution = parseInt('0x' + hex.substring(5, 9), 16);
            callback(null, {
                'status': status,
                'vertical': verticalResolution,
                'horizontal': horizontalResolution
            });
        }));
    }
],
// optional callback
function(err, results) {
    status = results[0];
    return results[0];
});

console.log(exports.getResolution);

I have tried callback hell, Promises, bluebird, ES6 async functions, and a bunch of other solutions but I just can't figure this one out. My most recent attempt uses the async node module to try and execute the code asynchronously, which works, but now I just need to get exports.getResolution to return the actual value the final callback receives. What am I doing wrong? What can I do to make this work? Thank you.

Anthony Jesmok
  • 449
  • 5
  • 12

2 Answers2

1

It's not a good idea to try to make an async call synchronous. What you need to do is register a method that executes when the result is there. Usually those methods are called callbacks, but Promises are a better way of accomplishing waiting for an async result.

exports.getResolution = function() {
    return new Promise(function(resolve, reject) {
        function receiveHandler(received) {
            var hex = bufferlib.sortReceivedHex(received);
            var status = parseInt('0x' + hex.substring(0, 1), 16);
            var verticalResolution = parseInt('0x' + hex.substring(1, 4), 16);
            var horizontalResolution = parseInt('0x' + hex.substring(5, 9), 16);

            // If status would say something about it's success you could also
            // use reject instead of resolve to indicate failure
            resolve({
                'status': status,
                'vertical': verticalResolution,
                'horizontal': horizontalResolution
            });
        }

        board.sendAndReceive(bufferlib.generateBuffer("read", "0x00001220", "0x00000004"), receiveHandler);
    }
}

// Usage
exports.getResolution().then(function(response) {
  console.log('succesfully received response:', response);
}, function(response) {
  console.log('something went wrong:', response)
});
meinaart
  • 107
  • 4
0

The correct way to do this would be to give your getResolution function a callback parameter. This is how it really should be done.

exports.getResolution = function(callback) {
    board.sendAndReceive(bufferlib.generateBuffer("read", "0x00001220", "0x00000004"), function(received) {
        var hex = bufferlib.sortReceivedHex(received);
        var status = parseInt('0x' + hex.substring(0, 1), 16);
        var verticalResolution = parseInt('0x' + hex.substring(1, 4), 16);
        var horizontalResolution = parseInt('0x' + hex.substring(5, 9), 16);
        callback(null, {
            'status': status,
            'vertical': verticalResolution,
            'horizontal': horizontalResolution
        });
    });
}


console.log(exports.getResolution(function (err, results) {
    console.log(results);
}));

The above way is the correct way of doing things in JS. But, if you absolutely need to make getResolution look synchronous, then you might want to check out this answer. But it seems that you will need to modify some of your board functions to allow for polling...

Community
  • 1
  • 1
mkhanoyan
  • 1,958
  • 18
  • 15
  • Thank you for your response. I really would like to avoid potential callback hell if possible, but I appreciate the time and thought you put into your response. – Anthony Jesmok Jan 06 '17 at 13:19