0

arguments et and instance, passed to the function which is promisified are not visible (seen as null) in the return new promise block. Note:

rp = require('request-promise');
Promise = require('bluebird');

.. and some of my own modules like urlLib are 'required' at the top. rp library is promisified request library... It works if I explicitly set et and instance variables inside the return statement. (see commented et and instance declarations).

module.exports.getEntityInstance = function (et, instance) {

return new Promise(function(resolve, reject) {

    // explicit setting, to test, works fine.
    // var et = "device", instance = "33";

    if ((!et) || (!instance)) {
        // ****** FAILING HERE *******
        reject(new Error(utilLib.errorAsJSON ("Invalid et/instance arg")));
    }
    OPTS.url = base_url + et + "/" + instance;
    rp(OPTS)
        .then(function (data) {
            resolve(data)
        })
    .catch(function (err) {
            reject(err);
        });
});
}

Here's the unadulterated code:

module.exports.em7GetEntityInstance = function (et, instance) {

log.info("----- et before promise:(" + et + ")");
log.info("----- instance before promise:(" + instance + ")");

return new Promise(function(resolve, reject) {
    // var et = "device";
    // var instance = "33";

    // if null or undefined...
    if (!et || !instance) {
        log.error("---- et and/or instance args null.  rejecting");
        reject(new Error(utilLib.errorAsJSON ("getEntityInstace():Invalid entity type argument")));
    }
    var et = et.toLowerCase().trim();
    var url = baseurl + et + "/" + instance
    log.info("url:(" + url + ")");
    OPTS.url = url;
    rp(OPTS)
        .then(function (data) {
            log.debug ("success. invoking resolve()");
            resolve(data)
        })
    .catch(function (err) {
            log.error("+++ rp failed:(" + err  + ")");
            reject(err);
        });
});

}

And the log statements (its a server process (no console.log). Using winston log module.

2016-05-05T15:44:06.866Z - info: ----- et before promise:(device)
2016-05-05T15:44:06.867Z - info: ----- instance before promise:(33)
2016-05-05T15:44:06.867Z - error: ---- et and/or instance args null.  rejecting
user3213604
  • 407
  • 1
  • 7
  • 18
  • 1
    They *are* visible unless you did shadow them by re-declaring `var et, instance`. Please show us your call, it's more likely that you passed in `null`. – Bergi May 05 '16 at 15:28
  • 1
    They'll be visible. What else happens in that `.getEntityInstance()` function? Have you used `console.log()` or the browser debugger to see what values the parameters have *outside* the Promise? – Pointy May 05 '16 at 15:28
  • Avoid the [`Promise` constructor antipattern](http://stackoverflow.com/q/23803743/1048572)! Rather [use `Promise.reject`](http://stackoverflow.com/q/35856041/1048572). – Bergi May 05 '16 at 15:29
  • Yes I used logging just after entering getEntityInstance and JUST after entering return - I see null. I have commented out the settings because i wanted to test to make sure the rest of the functionality works as expected IF values are available - and it does. So the now commented shadowing was for testing. @Bergi - can you please suggest what's the correct pattern here to avoid my antipattern please? => I see the link and that should work!! - as there is no explicit wrapper return(function()){} there. While i do that though, any suggestions why above's failing? – user3213604 May 05 '16 at 15:30
  • @user3213604: Please post the code that includes the `console.log` statements and the exact console output you are getting. – Bergi May 05 '16 at 15:32
  • I have sanitized the posted codefor code clarity... I am not shadowing the variables. I added them there to see IF they are available inside return, it works correctly. Here's from my log: `2016-05-05T15:00:06.948Z - info: ----- et before promise:(device) 2016-05-05T15:00:06.948Z - info: ----- instance before promise:(33) 2016-05-05T15:00:06.948Z - error: +++++ et null. rejecting` – user3213604 May 05 '16 at 15:35
  • @Bergi: added entire code. followed by logs (fresh execution). – user3213604 May 05 '16 at 15:47

1 Answers1

1

The var et in your inner function does shadow the variable with the same name from the outer scope. It's undefined when the test is evaluted.

Avoid the var, use a different variable name, or just do

var url = baseurl + et.toLowerCase().trim() + "/" + instance;

without the intermediate variable at all.


But you shouldn't use an inner function at all, rather do

module.exports.em7GetEntityInstance = function(et, instance) {
    log.info("----- et before promise:(" + et + ")");
    log.info("----- instance before promise:(" + instance + ")");
    // if null or undefined...
    if (et==null || instance==null) {
        log.error("---- et and/or instance args null.  rejecting");
        return Promise.reject(new Error(utilLib.errorAsJSON ("getEntityInstace():Invalid entity type argument")));
    }
    var url = baseurl + et.toLowerCase().trim() + "/" + instance;
    log.info("url:(" + url + ")");
    OPTS.url = url;
    return rp(OPTS).then(function(data) {
        log.debug ("success. invoking resolve()");
        return data;
    }, function(err) {
        log.error("+++ rp failed:(" + err  + ")");
        throw err;
    });
};
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • First of all the commented out var et and var instance just inside the 'return' function were to test (purposefully shadow, so I have values I expect to test if the rest of the functionailty works. But those stayed commented as shown in the code Furthermore, even if I use et and instance directly in the URL - I don't reach there. Lastly, I do need to promisify it all, since I am invoking this function from another module - which uses the promise pattern over this function. That 'rp' module supports promises is incidental. I need entire function promisified for use outside this module. – user3213604 May 05 '16 at 15:57
  • I did not mean the commented out `var et`, I meant the one in the line `var et = et.toLowerCase().trim();`. – Bergi May 05 '16 at 16:00
  • I see! but I am just not reaching that point - since the failure occurs before that. However - I noticed one change you did in your suggested snippet => and that is 'RETURN" rp(opts)..... which my earlier code didn't have. all the code before RP is invoked is synchronous - so no issues and 'rp' IS a promise anyway and it should work. Let me try that:) – user3213604 May 05 '16 at 16:02
  • I don't understand what your problem with promisification is? My version works just like yours, always returning promises. – Bergi May 05 '16 at 16:02
  • @user3213604: I doesn't matter whether evaluation reaches that point or not, `var et` is a variable declaration that is hoisted to the function scope and shadows the `et` variable from the outer scope. – Bergi May 05 '16 at 16:03
  • AHHH of course! forgot hoisting!! anyway, let me change the code to return rp()... and see what happens. Thanks. – user3213604 May 05 '16 at 16:05
  • yay. The problem WAS hoisting!! Thanks a bunch @Bergi! Its often easy to get sucked into believing something complex is going wrong - when often its the simplest things. thanks again. – user3213604 May 05 '16 at 16:07