为什么我没有得到警告"承诺是在处理程序中创建的,但未从它返回"?

时间:2017-11-23 19:02:00

标签: javascript node.js promise bluebird

编辑:更清楚 - 我在下面的示例中没有收到警告。我想知道为什么,看看会打印警告的示例代码。

在我的Node.js项目中,我使用了bluebird Promises库。我观察了一些我收到警告的情况:

  

警告:承诺是在处理程序中创建的,但未从中返回

据我所知,当承诺没有连接到任何承诺链时会出现问题。

我试图完全理解这是如何工作的,以及在上述案例中究竟是什么问题。为此,我从the documentation获得了榜样。

以下是基于我未收到任何警告的文档示例的代码示例:

const Promise = require('bluebird');

function getUser() {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log('get user');
            resolve('userId');
        }, 4000);
    });
}

function getUserData(userId) {
    new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log('get user data');
            resolve('userData');
        }, 5000);
    });
}

getUser().then(function(user) {
    getUserData(user);
}).then(function(userData) {
    // userData is undefined as expected
    console.log('Data: ', userData);
});

控制台输出:

/usr/local/opt/node@6/bin/node test.js
get user
Data:  undefined
get user data

Process finished with exit code 0

有谁知道为什么我的案子中没有警告以及如何重现它?

编辑:我使用的是Node v6.11.3和Bluebird 3.1.1

根据Pierre Clocher的回答,我也尝试了

getUser().then(function(user) {
    getUserData(user);
}).then(function(userData) {
    console.log('Data: ', userData);
    // userData is undefined
    throw new Error();
}).catch(function (error) {
    console.log('error: ', error);
});

也没有任何警告。

控制台输出:

/usr/local/opt/node@6/bin/node test.js
get user
Data:  undefined
error:  Error
    at test.js:64:11
    at tryCatcher (/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/node_modules/bluebird/js/release/promise.js:693:18)
    at Async._drainQueue (/node_modules/bluebird/js/release/async.js:133:16)
    at Async._drainQueues (/node_modules/bluebird/js/release/async.js:143:10)
    at Immediate.Async.drainQueues (/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:672:20)
    at tryOnImmediate (timers.js:645:5)
    at processImmediate [as _immediateCallback] (timers.js:617:5)
get user data

Process finished with exit code 0

检查Bluebird.js来源

如果有人更熟悉Bluebird来源,我已经跨源搜索并找到有警告检查的地方(link to source):

if (returnValue === undefined && promiseCreated !== null &&
        wForgottenReturn) {
....

}
var msg = "a promise was created in a " + name +
    "handler " + handlerLine + "but was not returned from it, " +
    "see <link to goo.gl removed>" +
    creatorLine;
promise._warn(msg, true, promiseCreated);

使用调试器我检查过, returnValue 在我的情况下未定义, wForgottenReturn 标志设置为true但 promiseCreated 为空,因此警告是没打印。我会将此解释为像Promise通过我的示例中的getUserData(user)未被检测为创建/未处理。

3 个答案:

答案 0 :(得分:3)

我会回答我自己的问题,因为我找到了捕获的位置。

简答:问题是只有在配置启用警告时才会在控制台中打印警告。

<强>解释

在网上搜索时,我在Bluebird github上找到了这个issue reported。在示例代码中,我看到他们使用以下代码手动更新了Bluebird配置:

Promise.config({
    warnings: true,
    longStackTraces: true
});

我在运行代码之前做了同样的事情:

Promise.config({
    warnings: true,
    longStackTraces: true
});

function getUser() {
    ...
}

function getUserData(userId) {
    ...
}

getUser().then(function(user) {
    getUserData(user);
}).then(function(userData) {
    // userData is undefined as expected
    console.log('Data: ', userData);
});

并且输出最终带有警告:

/usr/local/opt/node@6/bin/node test.js
get user
(node:96276) Warning: a promise was created in a handler at test.js:71:5 but was not returned from it, see <goo.gl link removed>
    at new Promise (node_modules/bluebird/js/release/promise.js:79:10)
Data:  undefined
get user data

Process finished with exit code 0

进一步检查我还发现,如果NODE_ENV变量设置为“development”,则无需手动设置Bluebird配置以查看警告。在“开发”的情况下,这些功能自动启用。这也在this API reference中描述。

答案 1 :(得分:-3)

你需要在回调中写回车。

.then(function(data){return getusersata()})

这样你需要在getuserdata

中返回promise
return new Promise

答案 2 :(得分:-3)

问题是出现了错误,并且您的承诺流上没有任何.catch()方法。你的例子并没有抛出任何你没有任何警告的原因。

试试看,你会看到警告:

getUser().then(function(user) {
    return getUserData(user);
}).then(function(userData) {
    // userData is undefined => now it is (you need to return previous Promise)
   throw new Error(); 
});

此处出现警告,因为错误。但是,如果你添加.catch(console.error),它就会赢得