kristof43
kristof43

Reputation: 23

Callback to Promises (nodes7)

I'm trying convert callback functions from nodeS7 API to promises. There is the code with callback, whit work correctly:

var nodes7 = require('nodes7');  
var conn = new nodes7;
var doneReading = false;
var doneWriting = false;

var variables = { 
          TEST5: 'DB1,REAL4',
};

conn.initiateConnection({port: 102, host: '192.168.0.2', rack: 0, slot: 1}, connected);

function connected(err) {
    if (typeof(err) !== "undefined") {
        // We have an error.  Maybe the PLC is not reachable.
        console.log(err);
        process.exit();
    }
    conn.setTranslationCB(function(tag) {return variables[tag];}); 
    conn.addItems(['TEST5']);
    conn.readAllItems(valuesReady);
}

function valuesReady(anythingBad, values) {
    if (anythingBad) { console.log("SOMETHING WENT WRONG READING VALUES!!!!"); }
    console.log(values);   // return {'TEST5': 23.5}
    doneReading = true;
    if (doneWriting) { process.exit(); }
}

Now I'm trying do something like that:

var nodes7 = require('nodes7');  
var conn = new nodes7;

function readVal(){
    return new Promise((resolve) => {
         conn.initiateConnection({port: 102, host: '172.16.85.10', rack: 0, slot: 1}, resolve);
    })    
}
function connected() {
    conn.addItemsNow(['DB12,REAL140']);

    return new Promise((resolve) => {
        conn.readAllItems(resolve);
      });
}
async function testAsync(dataToRead){
    try {
        await readVal();

        const readAll = await connected();
        console.log(readAll);
    }catch(e){
        console.log(e);
    }

}
testAsync();

Unfortunately, I still obtain readAll = false, but should be = {'DB12,REAL140': 23:45}. Could you point me what is wrong?

Upvotes: 1

Views: 327

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370799

The readAllItems callback - called valuesReady in your first code - accepts two parameters. The first is a possible error, and the second is the actual result:

conn.readAllItems(valuesReady);

// ...

function valuesReady(anythingBad, values) {
    if (anythingBad) { console.log("SOMETHING WENT WRONG READING VALUES!!!!"); }
    console.log(values);   // return {'TEST5': 23.5}
    doneReading = true;
    if (doneWriting) { process.exit(); }
}

But in your second code, the first parameter is being used by the resolve callback (and any subsequent arguments passed to resolve get ignored). So, as is, you're ending up with a resolve value of the anythingBad, which will be falsey under normal circumstances. That's why you're getting false at the moment.

Try rejecting with the first (error) parameter if it exists, and resolving with the second (resolved values) parameter otherwise:

function connected() {
    conn.addItemsNow(['DB12,REAL140']);
    return new Promise((resolve, reject) => {
        conn.readAllItems((anythingBad, values) => {
            if (anythingBad) reject(anythingBad);
            else resolve(values);
        });
   });
}

You should also have the readVal reject in the case of an error (it will currently always resolve, which is probably not what you want):

function readVal(){
    return new Promise((resolve, reject) => {
         conn.initiateConnection({port: 102, host: '172.16.85.10', rack: 0, slot: 1}, (err) => {
             if (err) reject(err);
             else resolve();
         });
    })    
}

You can also use util.promisify to translate the callbacks to Promises automatically, but it looks a bit awkward since it's only operating on the conn (and needs to preserve its calling context, while not changing the nodes7 prototype):

const { promisify } = require('util');

const initiateConnectionPromisified = promisify(conn.initiateConnection).bind(conn);
const readAllItemsPromisified = promisify(conn.readAllItems).bind(conn);

(async () => {
  await initiateConnectionPromisified({port: 102, host: '192.168.0.2', rack: 0, slot: 1});
  conn.setTranslationCB(function(tag) {return variables[tag];}); 
  conn.addItems(['TEST5']);
  await readAllItemsPromisified();
})();

Upvotes: 2

Related Questions