gpt4 book ai didi

javascript - Promise.all 与 try/catch 模拟

转载 作者:行者123 更新时间:2023-12-01 03:55:25 26 4
gpt4 key购买 nike

我目前正在浏览并尝试熟悉 Promise,我将跳过介绍性概念,并深入了解问题的实质。在 NodeJS 中,使用库 BlueBird 。我不想推迟函数调用,我也不想过多地污染代码,即使这是熟悉前提的介绍性编码,因为当尝试更高级的概念时,我会得到迷失在他们身上。我尝试将“asyn/await”与 try block 一起使用,但上帝是代码困惑,并且不起作用......或多或少的指导方针:

  • 我不想使用 Promise.settle,我仍然想在函数拒绝时退出,如果出现错误,我只想留在 Catch block 内。
  • 我不想以某种奇怪的方式使用 async/await、yield 或生成器来停止代码流,因为这不利于预期的实践。
  • 如果处理此问题的预期解决方案是错误的,请不要只是说它是错误的,我知道人们的时间很宝贵,但由于对语言工作原理的了解有限,因此可以向我提供尽可能多的文档,或者我错误的原因比不更值得赞赏。
  • 我已经在 CoffeeScript 中看到了这个概念的实现,但目前我没有看到转向该语法系统的可行理由,因为在接下来的几个月中我可能使用该语言的大多数内容都将是裸露的 Node back - 终端管理。

Promise 包含内置的 catch 机制,如果处理标准的单个 Promise,该机制可以完美地工作。

// Try/Catch style Promises
funcTwo = function(activate) {
return new Promise(function(resolve, reject) {
var tmpFuncTwo;
if (activate === true) {
tmpFuncTwo = "I'm successful"
resolve(tmpFuncTwo)
} else if (activate === false) {
tmpFuncTwo = "I'm a failure.";
reject(tmpFuncTwo)
} else {
tmpFuncTwo = "Oh this is not good."
throw new Error(tmpFuncTwo);
}
});
}

funcTwo(true)
.then(val => {
console.log("1: ", val)
return funcTwo()
})
.catch(e => {
console.log("2: Err ", e.message)
})

让我有些困惑的是试图坚持与 Promise.all 相同的前提,错误没有被处理,因为抛出直接推送到主 Controller 。从此代码段引发的异常永远不会进入 Catch block 。

funcThree = function(val) {
return new Promise(function(resolve, reject) {
if (val > 0)
resolve((val + 1) * 5)
else if (val < 0)
reject(val * 2)
else
throw new Error("No work for 0");
})
}
// Output in Dev Console
/*
Extrending to the catch block handling, This will fail, the exception is thrown, and ignores the catch block. Terminating the program.
*/
Promise.all([funcThree(1), funcThree(0), funcThree(-3)])
.then(function(arr) {
for (var ind = 0; ind < arr.length; ind++) {
console.log(arr)
};
}, function(arr) {
console.log(arr)
})
.catch(function(e) {
console.log("Error")
})

我尝试了一种简单的解决方法,但我对这门语言有点陌生,并且不确定这是否遵循“最佳实践”,因为它们是从 Python 指南中灌输到我的脑海中的。

// Promise all, exceptionHandling
funcThree = (val) => {
return new Promise(function(resolve, reject) {
if (val > 0)
resolve((val + 1) * 5)
else if (val < 0)
reject(val * 2)
else {
var tmp = new Error("No work for 0");
tmp.type = 'CustomError';
reject(tmp);
}
})
}

/*
This works, and doesn't cause any type of mixup
*/
Promise.all([funcThree(1), funcThree(0), funcThree(-3)])
.then(
arr => {
for (var ind = 0; ind < arr.length; ind++) {
console.log(arr)
};
}, rej => {
if (rej.type == 'CustomError')
throw rej;
console.log(arr)
})
.catch(e => {
console.log("Catching Internal ", e.message)
})

这是使用 Native Promise 库以及 bluebird

有没有一种方法可以更本地化地处理这个问题,

关于jfriend00的评论。我的意思是说,我不希望异常由 try-catch block 之外的任何东西处理。当我尝试使用与正常 promise 相同的格式时,一切都完美对齐,并且我的捕获得到确认,错误得到处理。由于 Promise.all 只能解析/拒绝,我认为没有一种干净的方法来委托(delegate)第二个代码片段中第二次调用 funcTwo 引发的异常。或多或少我不确定我所做的解决方法是否是一个好的解决方案,或者是否会导致一些深层问题随着代码的扩展。

最佳答案

Since Promise.all can only ever resolve/reject I don't think that there is a clean way of delegating the exception that is thrown from the second call to funcTwo in the second code snippet.

在您的这个代码块中:

// Try/Catch style Promises
funcTwo = function(activate) {
return new Promise(function(resolve, reject) {
var tmpFuncTwo;
if (activate === true) {
tmpFuncTwo = "I'm successful"
resolve(tmpFuncTwo)
} else if (activate === false) {
tmpFuncTwo = "I'm a failure.";
reject(tmpFuncTwo)
} else {
tmpFuncTwo = "Oh this is not good."
throw new Error(tmpFuncTwo);
}
});
}

throwreject() 之间没有区别。 throw 被 Promise 构造函数捕获并转换为 reject()。就我个人而言,我更喜欢在这种情况下仅使用 reject(),因为我认为函数调用比异常要快一些。

我不知道这是否已编入规范,但通常认为使用 Error 对象拒绝是一个好主意。所以,我会像这样编写代码:

function funcTwo(activate) {
return new Promise(function(resolve, reject) {
if (activate === true) {
resolve("I'm successful");
} else {
let errMsg = activate === false ? "I'm a failure." : "Oh this is not good.";
reject(new Error(errMsg));
}
});
}

Promise 要么解决,要么拒绝。没有与拒绝不同的第三种错误情况。异常(exception)只会变成拒绝。因此,如果您要返回三种状态(如上面的代码),那么您必须决定如何将这三种状态放入 resolvereject

由于这只是示例代码,因此这里没有具体的建议。如果 activate === false 实际上不是一个错误,只是一种不同类型的完成,不应该中止 Promise.all() 中的其他 promise ,那么你' d 希望该情况为 resolve(),而不是 reject()。但是,没有硬性规定什么是什么 - 它实际上只取决于您希望调用者的行为变得自然和简单,因此它会因情况而异。

此外,如果您不控制这里的 funcTwo 中的代码,那么您可以在传递之前在其上放置一个 .catch() 处理程序它到 Promise.all() 并且您可以将特定的拒绝转换为解决方案(如果您希望 Promise.all() 逻辑以这种方式工作)。 promise 链,以便您可以在将它们传递到更高级别的操作之前修改它们的输出。它类似于在较低级别使用 try/catch 来捕获异常并处理它,因此较高级别的代码不必看到它(有时是适当的)。

More or less I'm not sure if what I've done as a workaround," reject, check if reject passed forward an error, and then throw it if it did", is a good solution or if it will cause some deep problem as code expands.

在您的 Promise.all() 代码中:

/*
This works, and doesn't cause any type of mixup
*/
Promise.all([funcThree(1), funcThree(0), funcThree(-3)]).then(arr => {
for (var ind = 0; ind < arr.length; ind++) {
console.log(arr[index]);
}
}, rej => {
if (rej.type == 'CustomError')
throw rej;
console.log(arr)
}).catch(e => {
console.log("Catching Internal ", e.message)
})

您的第一个拒绝处理程序并没有真正帮助您。它不会做任何您在一个 .catch() 处理程序中无法完成的事情。让我重复一遍。 Promise 仅有两个结果 rejectresolve。异常(exception)情况没有第三种结果。 Promise 回调中发生的异常只会变成拒绝。因此,您上面的代码可以更改为:

/*
This works, and doesn't cause any type of mixup
*/
Promise.all([funcThree(1), funcThree(0), funcThree(-3)]).then(arr => {
for (var ind = 0; ind < arr.length; ind++) {
console.log(arr)
};
}).catch(e => {
// there is no value for arr here, no result - only a reject reason
console.log("Catching Internal ", e.message)
if (rej.type === "CustomError") {
// do something special for this type of error
}
// unless you rethrow here, this rejection will be considered handled
// and any further chained `.then()` will see the promise as resolved
// but since there is no return value, the promise will be resolved
// with an undefined result
});

如果您想尽早捕获 funcThree() 中的拒绝,以便仍可以跟踪 Promise.all() 中的其余 Promise,并且仍然得到他们的结果,那么你可以得到一个 Promise.settle() 实现,它将遵循所有的 promise 来得出结论,无论有多少拒绝,或者你可以编写自己的特殊情况:

function funcFour(val) {
return funcThree(val).catch(err => {
// catch and examine the error here
if (err.type === "CustomError") {
// allow things to continue on here for this specific error
// and substitute null for the value. The caller will have
// to see null as a meaningful result value and separate from
// a non-null result
return null;
} else {
// Not an error we recognize, stop further processing
// by letting this promise reject
throw err;
}
});
}

Promise.all([funcFour(1), funcFour(0), funcFour(-3)]).then(arr => {
// got results, some might be null
console.log(arr);
}).catch(err => {
// got some error that made it so we couldn't continue
console.log(err);
});
<小时/>

我知道这都是风格观点,但是使用 Promise 的良好代码的好处之一是,您不再需要深缩进的代码,现在我看到人们添加了各种额外的缩进和根本不需要的行,并且似乎消除了干净 promise 编码的一些好处。

在这种情况下,.then().catch() 可以与它​​们遵循的 Promise 位于同一行。而且,无需在新行上开始内联函数定义。

关于javascript - Promise.all 与 try/catch 模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42739883/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com