【问题标题】:Bluebird warning "A promise was created in a handler but was not returned from it"蓝鸟警告“在处理程序中创建了一个承诺,但没有从它返回”
【发布时间】:2015-12-19 12:51:10
【问题描述】:

我收到有关未从 Bluebird 返回已创建承诺的警告,但我不明白为什么以及如何重写我的代码。

(我已尝试阅读 Bluebird API 页面和 anti-pattern page 上的警告,因为我怀疑这是我正在做的)

在我的 view.js 文件中:

var express = require('express'),
    router = express.Router(),
    settings = myReq('config/settings'),
    Sets = myReq('lib/Sets'),
    log = myReq('lib/utils').getLogger('View');

router.get('/:setId/', function(req, res, next) {
    var
        setId = req.params.setId,  
        user = req.user,
        set = new Sets(setId, user);

    log.info('Got a request for set: ' + setId);

    // The below line gives the warning mentioned
    set.getSet().then(function(output) {
        res.send(output);

    }).error(function(e){
        log.error(e.message, e.data);
        res.send('An error occurred while handling set:' + e.message);
    });

});

module.exports = router;

在我的 Sets.js 文件中,我有:

var
    Promise = require('bluebird'),
    OE = Promise.OperationalError,
    settings = myReq('config/settings'),
    UserData = myReq('lib/userData'),
    log = myReq('lib/utils').getLogger('sets'),
    errorToSend = false;

module.exports = function(setId, user) {
    var 
        sets = myReq('lib/utils').getDb('sets');

    return {

        getSet : function() {

            log.debug('Getting set')

            return sets.findOneAsync({
                setId:setId
            }).then(function(set){
                if ( set ) {
                    log.debug('got set from DB');
                } else {
                    set = getStaticSet(setId);
                    if ( ! set ) {
                        throw new OE('Failed getting db records or static template for set: ' + setId );
                    }
                    log.debug('got static set');
                }

                log.debug('I am handling set')

                if ( ! checkSet(set) ) {
                    var e = new OE('Failed checking set');
                    e.data = set;
                    throw e;
                }

                return {
                    view : getView(set),
                    logic : set.logic,
                    canEdit : true,
                    error : errorToSend
                };

            });
        }
    };
};

所以我的 view.js 文件中带有“set.getSet()”的行给出了关于不返回创建的承诺的警告。该脚本似乎仍然按照我的预期执行,但我不明白为什么会收到警告。

堆栈跟踪:

Warning: a promise was created in a handler but was not returned from it
    at Object.getSet (C:\dev\infoscrn\lib\Sets.js:36:25)
    at C:\dev\infoscrn\routes\view.js:39:20
    at Layer.handle [as handle_request] (C:\dev\infoscrn\node_modules\express\lib\router\layer.js:82:5)
    at next (C:\dev\infoscrn\node_modules\express\lib\router\route.js:110:13)
    at Route.dispatch (C:\dev\infoscrn\node_modules\express\lib\router\route.js:91:3)
    at Layer.handle [as handle_request] (C:\dev\infoscrn\node_modules\express\lib\router\layer.js:82:5)
    at C:\dev\infoscrn\node_modules\express\lib\router\index.js:267:22
    at param (C:\dev\infoscrn\node_modules\express\lib\router\index.js:340:14)
    at param (C:\dev\infoscrn\node_modules\express\lib\router\index.js:356:14)
    at Function.proto.process_params (C:\dev\infoscrn\node_modules\express\lib\router\index.js:400:3)
    at next (C:\dev\infoscrn\node_modules\express\lib\router\index.js:261:10)
    at Function.proto.handle (C:\dev\infoscrn\node_modules\express\lib\router\index.js:166:3)
    at router (C:\dev\infoscrn\node_modules\express\lib\router\index.js:35:12)
    at Layer.handle [as handle_request] (C:\dev\infoscrn\node_modules\express\lib\router\layer.js:82:5)
    at trim_prefix (C:\dev\infoscrn\node_modules\express\lib\router\index.js:302:13)
    at C:\dev\infoscrn\node_modules\express\lib\router\index.js:270:7
    at Function.proto.process_params (C:\dev\infoscrn\node_modules\express\lib\router\index.js:321:12)
    at next (C:\dev\infoscrn\node_modules\express\lib\router\index.js:261:10)
    at C:\dev\infoscrn\node_modules\express\lib\router\index.js:603:15
    at next (C:\dev\infoscrn\node_modules\express\lib\router\index.js:246:14)

【问题讨论】:

  • 可能在set.getSet函数中。只需分享您的堆栈跟踪,因为这将有助于确定问题的确切位置。
  • 这是堆栈跟踪:
  • 我已尝试更新所有部门,但警告仍然存在。我真的很想继续收到这些类型的警告,因为我发现它们很有用,所以我不想在全球范围内关闭它们。但是这个我不明白.... :-)
  • 你找到解决办法了吗?
  • @RémiBecheras 不,还没有……

标签: node.js express bluebird


【解决方案1】:

首先,尝试update all your dependencies。有一个最新版本的 Bluebird,它修复了 an issue involving this warning

接下来,请确保您return from all your handlers

然后,如果您仍然收到警告(就像我一样),您可以disable this specific warning。我选择通过在我的环境中设置 BLUEBIRD_W_FORGOTTEN_RETURN=0 来做到这一点。

【讨论】:

  • babel6 await async 有问题,因此我确认必须在 Node.js 上禁用它
  • 你如何禁用它?
【解决方案2】:

不要禁用警告。他们在那里是有原因的。

典型的模式是,如果你的 onfulfill 或 onreject 处理程序导致一个 Promise 被构造,它将从处理程序返回该 Promise(或从它派生的某个链),以便该链采用该 Promise 的状态。

因此,Bluebird 会跟踪它何时运行您的处理程序函数之一,并跟踪何时调用它的 Promise 构造函数。如果它确定在您的处理程序运行时在任何点创建了一个 Promise(包括调用堆栈中的任何位置),但该 Promise 没有从您的处理程序返回,它发出此警告是因为它认为您可能忘记编写 return 语句。

因此,如果您合法地不关心在处理程序中创建的 Promise,那么您所要做的就是从处理程序显式返回一些内容。如果您不关心从处理程序返回的内容(即,如果您不关心 Promise 实现的值),则只需返回 null。无论您返回什么,显式返回(特别是undefined 以外的返回值)都会告诉 Bluebird 您认为自己知道自己在做什么,并且它不会发出此警告。

【讨论】:

  • 虽然我普遍同意“不要禁用警告。它们的存在是有原因的”的说法,但对于这个特定的警告,我认为它不适用。出现此警告是因为 bluebird 希望在某些情况下看到 return null; 语句 - 但如果您执行 resolve(); 并且没有更多代码,那么在代码中添加 return null; 是无用的噪音。
  • @kris 在这种情况下,我不太清楚resolve() 是什么。我同意在代码中添加return null 可能会产生一点额外的噪音,并且可能会让不知道它为什么存在的人感到困惑。我们为我们的团队决定的是定义一个等于null 的常量,命名为NO_PROMISE_RETURNED,然后返回它。
【解决方案3】:

确保您拥有return 声明的每个地方都适合我。

【讨论】:

    猜你喜欢
    • 2016-08-23
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 2017-11-02
    • 1970-01-01
    • 2016-03-01
    • 1970-01-01
    • 2016-10-18
    相关资源
    最近更新 更多