NodeJS Bluebird Promise 在处理程序中创建但没有从它返回

Posted

技术标签:

【中文标题】NodeJS Bluebird Promise 在处理程序中创建但没有从它返回【英文标题】:NodeJS Bluebird promise created in a handler but was not returned from it 【发布时间】:2017-01-30 09:47:10 【问题描述】:

我有以下 nodejs 代码作为快速中间件函数

Middleware.is_authenticated = function(req, res, next)

    if(req.system_session == undefined || req.system_session.login_status == false) return res.status(401).send(errors: true, error: 'invalid_session', session: req.system_session).end();

    Session.validate_session(req.system_session, req.ip, req.headers['user-agent'])

    .then(function(session)
    
        return next();
    )

    .catch(function(err)
    
        req.system_session.destroy();
        return res.status(401).send(errors: true, error: err.message, session: req.system_session).end();
    );
;

我的 Session.validate_session 代码:

Session.validate_session = function(user, user_ip, user_agent)

    return new Promise(function(resolve, reject)
    
        if(user.user_id == null || user.user_name == null || user.user_rank == null || user.user_session == null || user_ip == null || user_agent == null) return reject(new Error('invalid_session'));

        new api_session(user_session: user.user_session).fetch(columns: ['user_id', 'user_name', 'user_rank', 'user_session', 'user_ip', 'user_agent'])

        .then(function(result)
        
            if(result == null) return reject(new Error('invalid_session'));

            return result.toJSON();
        )

        .then(function(session)
        
            if(session == null || session.user_id != user.user_id || session.user_name != user.user_name || session.user_rank != user.user_rank || session.user_ip != user_ip || session.user_agent != user_agent) return reject(new Error('invalid_session'));

            return resolve(session);
        )

        .catch(function(err)
        
            return reject(err);
        );
    );
;

一切都按原样工作,一切都在数据库中完美执行,以及解析“下一个”路线,甚至显示响应。但无论我尝试什么,我都会不断收到“在处理程序中创建了一个承诺,但没有从它返回”

Warning: a promise was created in a handler at middleware.js:12:11 but was not returned from it

at new Promise (/Users/Bill/Documents/app/node_modules/bluebird/js/release/promise.js:77:14)
at Object.Permission.permission_list (/Users/Bill/Documents/app/app/security/permission.js:8:10)
at PermissionService.permission_list (/Users/Bill/Documents/app/app/http/services/permission_service.js:6:14)
at Layer.handle [as handle_request] (/Users/Bill/Documents/app/node_modules/express/lib/router/layer.js:95:5)
at next (/Users/Bill/Documents/app/node_modules/express/lib/router/route.js:131:13)
at /Users/Bill/Documents/app/app/http/middleware.js:12:11
at processImmediate [as _immediateCallback] (timers.js:383:17)

From previous event:
at Middleware.is_authenticated (/Users/Bill/Documents/app/app/http/middleware.js:10:4)
at Layer.handle [as handle_request] (/Users/Bill/Documents/app/node_modules/express/lib/router/layer.js:95:5)
at next (/Users/Bill/Documents/app/node_modules/express/lib/router/route.js:131:13)
at Route.dispatch (/Users/Bill/Documents/app/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/Users/Bill/Documents/app/node_modules/express/lib/router/layer.js:95:5)
at /Users/Bill/Documents/app/node_modules/express/lib/router/index.js:277:22
at Function.process_params (/Users/Bill/Documents/app/node_modules/express/lib/router/index.js:330:12)
at next (/Users/Bill/Documents/app/node_modules/express/lib/router/index.js:271:10)
at clientSession (/Users/Bill/Documents/app/node_modules/client-sessions/lib/client-sessions.js:630:5)
at Layer.handle [as handle_request] (/Users/Bill/Documents/app/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/Users/Bill/Documents/app/node_modules/express/lib/router/index.js:312:13)
at /Users/Bill/Documents/app/node_modules/express/lib/router/index.js:280:7
at Function.process_params (/Users/Bill/Documents/app/node_modules/express/lib/router/index.js:330:12)
at next (/Users/Bill/Documents/app/node_modules/express/lib/router/index.js:271:10)
at SendStream.error (/Users/Bill/Documents/app/node_modules/express/node_modules/serve-static/index.js:121:7)
at emitOne (events.js:77:13)
at SendStream.emit (events.js:169:7)
at SendStream.error (/Users/Bill/Documents/app/node_modules/express/node_modules/send/index.js:275:17)
at SendStream.onStatError (/Users/Bill/Documents/app/node_modules/express/node_modules/send/index.js:392:12)

如果有人有任何解决方案,那就太好了。我在我的项目中有许多非常相似的承诺,而且它们都运行良好,但我就是无法理解这一点。

【问题讨论】:

第 12 行是 return next();? 我真的很想知道为什么你在validate_session 中没有收到关于Promise constructor antipattern 的警告 【参考方案1】:

这来自基于承诺的代码 (Session.validate_session) 和基于回调的代码 (next) 的混合。预计next() 调用要么不是异步的(不创建任何承诺),要么返回该承诺,但它没有(责备表达)。

有两种方法可以避免警告:

让 express 进行错误处理,如果发生错误,调用next。在这种情况下,您可以使用.asCallback method:

Middleware.is_authenticated = function(req, res, next) 
    if (req.system_session == undefined || req.system_session.login_status == false)
        var promise = Promise.reject(new Error('invalid_session'));
    else
        var promise = Session.validate_session(req.system_session, req.ip, req.headers['user-agent']);

    promise.asCallback(next);
;

正如warning explanation 所说,您可以显式地使用return null 而不是返回next() 产生的undefined 值:

Middleware.is_authenticated = function(req, res, next) 
    if (req.system_session == undefined || req.system_session.login_status == false)
        var promise = Promise.reject(new Error('invalid_session'));
    else
        var promise = Session.validate_session(req.system_session, req.ip, req.headers['user-agent'])
        .catch(function(err) 
            req.system_session.destroy();
            throw err;
        );

    promise.then(function(session) 
        next();
        return null;
    , function(err) 
        res.status(401).send(errors: true, error: err.message, session: req.system_session).end();
    );
;

【讨论】:

以上是关于NodeJS Bluebird Promise 在处理程序中创建但没有从它返回的主要内容,如果未能解决你的问题,请参考以下文章

nodejs使用request和bluebird编写的http请求模块

无法得到我在 nodejs / mongoose / bluebird 中返回的承诺

与 fs 和 bluebird 的承诺

Mongoose与bluebird结合使用实例

为啥在使用promise时使用Q,bluebird框架? [复制]

一个承诺的 mysql 模块将如何与 NodeJS 一起工作?