为什么需要立即使用我的 ES6 Promise Rejection 以避免出现控制台错误消息?
Why does my ES6 Promise Rejection need to be consumed immediately to avoid a console error message?
请注意:以下是在不同浏览器中表现不同的问题。所以也许这是一个浏览器实现问题。不管怎样,我都会喜欢一些建议。
在我的应用程序中,我创建了几个承诺,我可能要在未来相当长的一段时间内才会使用这些承诺。这应该没问题,毕竟是承诺。
如果存储的 promise 已解决,则没有问题。我可以在未来尽可能多地使用它,并且可以多次使用它。不出所料。
但是,如果被存储的承诺被拒绝,那就有问题了。除非我在做出拒绝后不久(不确定多快)消费该拒绝,否则控制台消息将在 Chrome 或 Firefox 中弹出,表明存在未捕获的承诺 rejection/error。 IE不弹出那个错误。
所以考虑下面的代码:
console.log("About to make a promise rejection.");
var foo = Promise.reject(new Error("Foo Rejected Promise."));
console.log("Promise rejection made.");
请注意,没有使用或消耗 promise foo。它只是存放起来以备将来使用。
IE 上的控制台如下所示:
About to make a promise rejection.
Promise rejection made.
这是意料之中的。但是,Chrome 上的相同代码将产生以下控制台:
About to make a promise rejection.
Promise rejection made.
Uncaught (in promise) Error: Foo Rejected Promise.(…)
Firefox 看起来很像 Chrome,除了围绕“未捕获”错误的措辞。
但问题是我打算稍后处理这个“错误”,当时我正在使用承诺。仅仅有一个被拒绝的承诺不应该导致控制台错误......如果我消费这个承诺并且不处理错误就会发生这种情况。
要模拟“更晚”的错误处理,请考虑对代码进行以下更改:
console.log("About to make a promise rejection.");
var foo = Promise.reject(new Error("Foo Rejected Promise."));
console.log("Promise rejection made.");
setTimeout(() => {
foo.catch((err) => {
console.log("Displaying " + err.message + " 10 seconds later.");
});
}, 10000);
现在在这种情况下,我们通过在超时后在控制台上显示一些内容来“处理”错误。现在 IE 仍然按照我的预期处理这个问题:
About to make a promise rejection.
Promise rejection made.
Displaying Foo Rejected Promise. 10 seconds later.
在这种情况下,Firefox 确实像 IE,并且准确地显示了这些消息,并且没有给我一个错误的控制台错误。
Chrome,但是,还是报错:
About to make a promise rejection.
Promise rejection made.
Uncaught (in promise) Error: Foo Rejected Promise.(…)
Displaying Foo Rejected Promise. 10 seconds later.
所以Chrome既抱怨我的错误没有被处理,又显示处理了
看来我可以使用以下看起来像是 hack 的代码来解决所有这些问题。基本上我在创建承诺时对错误进行了“假”处理,然后按照我以后想要的方式真正处理它:
console.log("About to make a promise rejection.");
var foo = Promise.reject(new Error("Foo Rejected Promise."));
foo.catch(() => { }); // Added this hack-ish code.
console.log("Promise rejection made.");
setTimeout(() => {
foo.catch((err) => {
console.log("Displaying " + err.message + " 10 seconds later.");
});
}, 10000);
但这是丑陋的代码。
我的问题是双重的 - 是否有某种方法可以查看 Chrome(以及某种程度上的 FireFox)正在做的事情并将其视为一种帮助?因为对我来说这看起来很糟糕。其次,有没有比假装处理错误更好的方法来解决这个问题?
提前致谢。
作为一个已经使用 promises 工作了几年的人,我理解为什么在 Chrome 中设置了这种行为。很容易忘记捕获被拒绝的 promise,如果 .then() 中有错误,将不会有任何通知,您的程序只会保持沉默。它可能很难调试。
function throwException(c){ return a.b = 2 ;} //a is not defined. throws exception.
let p = q.resolve("a")
.then(x => x + "b")
.then(y => throwException(y))
.then(z=> z+"c"); //this will say nothing in Q library
当忘记捕获错误时,这很容易造成非常模糊的行为。
在 Q 库中,您有 .done() 函数来实际执行 Chrome 在这里所做的事情:
let p = q.resolve("a")
.then(x => x + "b")
.then(y => throwException(y))
.then(z=> z+"c")
.done(); //this will throw an exception.
因此,这是 promise 中的一个已知问题。 Chrome 只是决定让 .done() 成为默认行为,要求您明确 .catch(_=>{})
如果您想忽略失败的承诺。 Q 已决定将静默失败设置为默认设置,要求您明确使用 .done()
如果您希望在承诺失败时出现异常。如果您喜欢后一种方法,您总是可以包含一个 promise 库。恕我直言,这是一个品味问题。
任何有可能被拒绝的承诺都应该被处理,类似于异常。
不同步链接 promise 的可能性不大。但如果不会,则需要 'hack-ish' .catch(() => { })
同步处理拒绝。
Chrome promise rejection behavior put this
var foo = Promise.reject(new Error("Foo Rejected Promise."));
foo.catch(() => { }); // Added this hack-ish code.
setTimeout(() => {
foo.catch((err) => {
console.log("Displaying " + err.message + " 10 seconds later.");
});
}, 10000);
进入与
相同的错误处理船
try {
throw new Error("Foo"));
setTimeout(() => {
try {
throw new Error("Foo"));
} catch (err) {
console.log("Displaying " + err.message + " 10 seconds later.");
}
}, 10000);
} catch (err) {}
异常不会等10秒被下一个try...catch
捕捉到才被抛出吗?它甚至不会等待一个滴答声。它需要 'hack-ish' try { ... } catch (err) {}
块才能按预期执行。
这种行为早已为 Bluebird 库用户所熟知。 Bluebird 具有可调节的错误处理功能,即使在大规模情况下也能高效 debug promises。
该行为在 Angular 2 开发中也是已知的,它被强制用于 Zone.js 库的承诺。
由于 promise 调试的价值有限且适用于开发环境,因此可以在生产构建中修改或禁用本机 promise 的此行为:
if (typeof DEBUG_PROMISE === 'undefined') {
window.addEventListener('unhandledrejection', (e) => {
e.preventDefault();
console.warn(e.reason);
});
}
Here's more reading 关于这个问题。
请注意:以下是在不同浏览器中表现不同的问题。所以也许这是一个浏览器实现问题。不管怎样,我都会喜欢一些建议。
在我的应用程序中,我创建了几个承诺,我可能要在未来相当长的一段时间内才会使用这些承诺。这应该没问题,毕竟是承诺。
如果存储的 promise 已解决,则没有问题。我可以在未来尽可能多地使用它,并且可以多次使用它。不出所料。
但是,如果被存储的承诺被拒绝,那就有问题了。除非我在做出拒绝后不久(不确定多快)消费该拒绝,否则控制台消息将在 Chrome 或 Firefox 中弹出,表明存在未捕获的承诺 rejection/error。 IE不弹出那个错误。
所以考虑下面的代码:
console.log("About to make a promise rejection.");
var foo = Promise.reject(new Error("Foo Rejected Promise."));
console.log("Promise rejection made.");
请注意,没有使用或消耗 promise foo。它只是存放起来以备将来使用。
IE 上的控制台如下所示:
About to make a promise rejection.
Promise rejection made.
这是意料之中的。但是,Chrome 上的相同代码将产生以下控制台:
About to make a promise rejection.
Promise rejection made.
Uncaught (in promise) Error: Foo Rejected Promise.(…)
Firefox 看起来很像 Chrome,除了围绕“未捕获”错误的措辞。
但问题是我打算稍后处理这个“错误”,当时我正在使用承诺。仅仅有一个被拒绝的承诺不应该导致控制台错误......如果我消费这个承诺并且不处理错误就会发生这种情况。
要模拟“更晚”的错误处理,请考虑对代码进行以下更改:
console.log("About to make a promise rejection.");
var foo = Promise.reject(new Error("Foo Rejected Promise."));
console.log("Promise rejection made.");
setTimeout(() => {
foo.catch((err) => {
console.log("Displaying " + err.message + " 10 seconds later.");
});
}, 10000);
现在在这种情况下,我们通过在超时后在控制台上显示一些内容来“处理”错误。现在 IE 仍然按照我的预期处理这个问题:
About to make a promise rejection.
Promise rejection made.
Displaying Foo Rejected Promise. 10 seconds later.
在这种情况下,Firefox 确实像 IE,并且准确地显示了这些消息,并且没有给我一个错误的控制台错误。
Chrome,但是,还是报错:
About to make a promise rejection.
Promise rejection made.
Uncaught (in promise) Error: Foo Rejected Promise.(…)
Displaying Foo Rejected Promise. 10 seconds later.
所以Chrome既抱怨我的错误没有被处理,又显示处理了
看来我可以使用以下看起来像是 hack 的代码来解决所有这些问题。基本上我在创建承诺时对错误进行了“假”处理,然后按照我以后想要的方式真正处理它:
console.log("About to make a promise rejection.");
var foo = Promise.reject(new Error("Foo Rejected Promise."));
foo.catch(() => { }); // Added this hack-ish code.
console.log("Promise rejection made.");
setTimeout(() => {
foo.catch((err) => {
console.log("Displaying " + err.message + " 10 seconds later.");
});
}, 10000);
但这是丑陋的代码。
我的问题是双重的 - 是否有某种方法可以查看 Chrome(以及某种程度上的 FireFox)正在做的事情并将其视为一种帮助?因为对我来说这看起来很糟糕。其次,有没有比假装处理错误更好的方法来解决这个问题?
提前致谢。
作为一个已经使用 promises 工作了几年的人,我理解为什么在 Chrome 中设置了这种行为。很容易忘记捕获被拒绝的 promise,如果 .then() 中有错误,将不会有任何通知,您的程序只会保持沉默。它可能很难调试。
function throwException(c){ return a.b = 2 ;} //a is not defined. throws exception.
let p = q.resolve("a")
.then(x => x + "b")
.then(y => throwException(y))
.then(z=> z+"c"); //this will say nothing in Q library
当忘记捕获错误时,这很容易造成非常模糊的行为。
在 Q 库中,您有 .done() 函数来实际执行 Chrome 在这里所做的事情:
let p = q.resolve("a")
.then(x => x + "b")
.then(y => throwException(y))
.then(z=> z+"c")
.done(); //this will throw an exception.
因此,这是 promise 中的一个已知问题。 Chrome 只是决定让 .done() 成为默认行为,要求您明确 .catch(_=>{})
如果您想忽略失败的承诺。 Q 已决定将静默失败设置为默认设置,要求您明确使用 .done()
如果您希望在承诺失败时出现异常。如果您喜欢后一种方法,您总是可以包含一个 promise 库。恕我直言,这是一个品味问题。
任何有可能被拒绝的承诺都应该被处理,类似于异常。
不同步链接 promise 的可能性不大。但如果不会,则需要 'hack-ish' .catch(() => { })
同步处理拒绝。
Chrome promise rejection behavior put this
var foo = Promise.reject(new Error("Foo Rejected Promise."));
foo.catch(() => { }); // Added this hack-ish code.
setTimeout(() => {
foo.catch((err) => {
console.log("Displaying " + err.message + " 10 seconds later.");
});
}, 10000);
进入与
相同的错误处理船try {
throw new Error("Foo"));
setTimeout(() => {
try {
throw new Error("Foo"));
} catch (err) {
console.log("Displaying " + err.message + " 10 seconds later.");
}
}, 10000);
} catch (err) {}
异常不会等10秒被下一个try...catch
捕捉到才被抛出吗?它甚至不会等待一个滴答声。它需要 'hack-ish' try { ... } catch (err) {}
块才能按预期执行。
这种行为早已为 Bluebird 库用户所熟知。 Bluebird 具有可调节的错误处理功能,即使在大规模情况下也能高效 debug promises。
该行为在 Angular 2 开发中也是已知的,它被强制用于 Zone.js 库的承诺。
由于 promise 调试的价值有限且适用于开发环境,因此可以在生产构建中修改或禁用本机 promise 的此行为:
if (typeof DEBUG_PROMISE === 'undefined') {
window.addEventListener('unhandledrejection', (e) => {
e.preventDefault();
console.warn(e.reason);
});
}
Here's more reading 关于这个问题。