【问题标题】:function args not visible inside return new Promise(function(resolve, reject)函数 args 在 return new Promise(function(resolve, reject) 内部不可见
【发布时间】:2016-05-05 15:26:48
【问题描述】:

参数et 和instance,传递给promisified 的函数在return new promise 块中不可见(被视为null)。 注意:

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

.. 和我自己的一些模块,如 urlLib,在顶部是“必需的”。 rp 库是承诺的请求库...如果我在 return 语句中明确设置 et 和实例变量,它就可以工作。 (参见注释的 et 和实例声明)。

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);
        });
});
}

这是纯正的代码:

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);
        });
});

}

还有日志语句(它是一个服务器进程(没有 console.log)。使用 winston 日志模块。

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

【问题讨论】:

  • 它们可见的,除非你通过重新声明 var et, instance 来隐藏它们。请告诉我们您的电话,您更有可能通过null
  • 它们将是可见的。 .getEntityInstance() 函数中还会发生什么?您是否使用过console.log() 或浏览器调试器来查看参数 Promise 之外具有哪些值?
  • 是的,我在输入 getEntityInstance 后使用日志记录,在输入 return 后使用日志记录 - 我看到 null。我已经注释掉了这些设置,因为我想测试以确保其余功能按预期工作,如果值可用 - 确实如此。所以现在评论的阴影是为了测试。 @Bergi - 你能建议这里的正确模式是什么,以避免我的反模式吗? => 我看到了链接,应该可以了!! - 因为那里没有明确的包装器 return(function()){}。虽然我这样做了,但有什么建议为什么上面失败了?
  • @user3213604:请发布包含console.log 语句的代码以及您获得的确切控制台输出。

标签: javascript node.js scope promise bluebird


【解决方案1】:

您的内部函数中的var et 确实会从外部范围中隐藏具有相同名称的变量。评估测试时是undefined

避免使用var,使用不同的变量名,或者只是这样做

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

完全没有中间变量。


但是you shouldn't use an inner function at all,宁可这样做

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;
    });
};

【讨论】:

  • 首先,在“return”函数中注释掉的 var et 和 var 实例将被测试(故意隐藏,所以我有值我希望测试其余的功能是否有效。但是那些保持注释,如代码所示此外,即使我直接在 URL 中使用 et 和 instance - 我没有到达那里。最后,我确实需要承诺这一切,因为我从另一个模块调用这个函数 - 这在这个函数上使用promise模式。'rp'模块支持promise是偶然的。我需要promisified整个函数在这个模块之外使用。
  • 我不是说被注释掉的var et,我指的是var et = et.toLowerCase().trim();中的那个。
  • 我明白了!但我只是没有达到这一点 - 因为失败发生在此之前。但是-我注意到您在建议的 sn-p => 中所做的一项更改,那就是“返回” rp(opts)..... 我之前的代码没有。调用 RP 之前的所有代码都是同步的-所以没有问题,“rp”无论如何都是一个承诺,它应该可以工作。让我试试看:)
  • 我不明白你对承诺的问题是什么?我的版本和你的一样,总是返回承诺。
  • @user3213604:我不管评估是否达到那个点,var et 是一个变量声明,它被提升到函数范围并从外部范围隐藏et 变量。
猜你喜欢
  • 2015-11-15
  • 2019-04-07
  • 2019-09-15
  • 2019-01-20
  • 1970-01-01
  • 2021-01-08
  • 1970-01-01
  • 2019-08-31
  • 2016-09-12
相关资源
最近更新 更多