Search code examples
node.jsnet-snmp

NodeJS Async/Await or Promise for net-snmp module


please someone help, I just cant get it. Can you please help on how to make async/await or promise (doneCb), so script waits for first vlc_snmp(..) to finish and then to call next? Example:

function doneCb(error) {
  console.log(final_result);
  final_result = [];
  if (error)
    console.error(error.toString());
}

function feedCb(varbinds) {
  for (var i = 0; i < varbinds.length; i++) {
    if (snmp.isVarbindError(varbinds[i]))
      console.error(snmp.varbindError(varbinds[i]));
    else {
      var snmp_rez = {
        oid: (varbinds[i].oid).toString()
        value: (varbinds[i].value).toString()
      };

      final_result.push(snmp_rez);
    }
  }
}

  var session = snmp.createSession(VLC_IP, "public", options);

  var maxRepetitions = 20;

  function vlc_snmp(OID) {
    session.subtree(OID_, maxRepetitions, feedCb, doneCb);
  }

 vlc_snmp(OID_SERIAL_NUMBER);
 //wait OID_SERIAL_NUMBER to finish and then call next
 vlc_snmp(OID_DEVICE_NAME);

Solution

  • You should be able to use the async / await statements to wait for your done callback to be called. We wrap this callback in the vlc_snmp function, and return a Promise. This allows us to use the await statement.

    I've mocked out some of the code that I don't have access to, it should behave somewhat similarly to the real code.

    The key point here is, when a function returns a Promise we can await the result in an async function, that will give you the behaviour you wish.

    final_result = [];
    const VLC_IP = "";
    const options = {};
    const OID_ = "OID_";
    const OID_SERIAL_NUMBER = "OID_SERIAL_NUMBER"
    const OID_DEVICE_NAME = "OID_DEVICE_NAME"
    
    
    // Mock out snmp to call feedcb and donecb
    const snmp = { 
        createSession(...args) { 
            return {
                subtree(oid, maxRepetitions, feedCb, doneCb) {
                    setTimeout(feedCb, 500, [{ oid, value: 42}])
                    setTimeout(doneCb, 1000);
                } 
            }
        },
        isVarbindError(input) { 
            return false;
        }
    }
    
    function doneCb(error) {
      console.log("doneCb: final_result:", final_result);
      final_result = [];
      if (error)
        console.error("doneCb: Error:", error.toString());
    }
    
    function feedCb(varbinds) {
      for (var i = 0; i < varbinds.length; i++) {
        if (snmp.isVarbindError(varbinds[i]))
          console.error(snmp.varbindError(varbinds[i]));
        else {
          var snmp_rez = {
            oid: (varbinds[i].oid).toString(),
            value: (varbinds[i].value).toString()
          };
    
          final_result.push(snmp_rez);
        }
      }
    }
    
    var session = snmp.createSession(VLC_IP, "public", options);
    
    var maxRepetitions = 20;
    
    function vlc_snmp(OID) {
        return new Promise((resolve,reject) => {
            session.subtree(OID, maxRepetitions, feedCb, (error) => {
                // This is a wrapper callback on doneCb
                // Always call the doneCb
                doneCb(error);
                if (error) { 
                    reject(error);
                } else { 
                    resolve();
                }
            });
        });
    }
    
    async function run_vls_snmp() {
        console.log("run_vls_snmp: Calling vlc_snmp(OID_SERIAL_NUMBER)...");
        await vlc_snmp(OID_SERIAL_NUMBER);
        console.log("run_vls_snmp: Calling vlc_snmp(OID_DEVICE_NAME)...");
        //wait OID_SERIAL_NUMBER to finish and then call next
        await vlc_snmp(OID_DEVICE_NAME);
    }
     
    run_vls_snmp();