为什么我没有收到警告 "a promise was created in a handler but was not returned from it"?

Why do I not get the warning "a promise was created in a handler but was not returned from it"?

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

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

Warning: a promise was created in a handler but was not returned from it

我了解当存在未连接到任何承诺链的承诺时会出现问题。

我正在尝试完全理解它是如何工作的,以及上述案例中的问题到底是什么。为此,我以 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 via getUserData(user) was not detected as created/unhandled.

回调里面需要写return

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

这样你需要 return 在 getuserdata

中承诺
return new Promise

问题是抛出了一个错误,而您的承诺流程中没有任何 .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) 就不会了。

我会回答我自己的问题,因为我找到了问题所在。

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

解释:

在网上搜索时,我在 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 配置即可查看警告。在 "development" 的情况下,此类功能会自动启用。 this API reference.

中也对此进行了描述