为什么在 JS 中使用异常来拒绝承诺? [英] Why are exceptions used for rejecting promises in JS?

查看:11
本文介绍了为什么在 JS 中使用异常来拒绝承诺?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我所指的规范位于 http://promises-aplus.github.io/promises-spec/.

当使用then()时,你可以返回一个promise,并在你想要的时候拒绝这个promise,或者你可以抛出一个异常来拒绝一个promise.

为什么 api 的设计方式不是如此,对于 then 函数,它会像原始的 promise 构造函数一样传递一个 resolve 和 reject 函数?

异常在许多语言中都很严重(我假设在 javascript 中也是如此)所以他们将它们用作流控制的选择似乎很奇怪.创建一个全新的承诺对象并返回它,只是为了拒绝它,增加了代码膨胀 IMO.如果抛出异常(例如语法错误,或者在未定义的对象上调用函数等),调试也会变得更加困难.

解决方案

为什么 api 的设计方式不是如此,对于 then 函数,它会像原始的 promise 构造函数一样传递一个 resolve 和 reject 函数?

实际上,该规范中的 API 是各种实现之间的共识.但是,可能导致这种情况的一些要点是:

  • then 是一个相当实用的方法.它的回调只应该接收一个数据参数,即承诺的结果值.
  • 将额外的 resolve/reject 函数传递给回调函数不适用于多个参数甚至可变参数函数.
  • then 通常用作普通映射函数.您只需返回新值,不需要resolve.
  • 当你真的想在你的回调中做一些异步的事情,你可以使用resolve/reject,你最好还是使用一个promise——你可以那就回来吧.

我曾经用可选的 resolve/reject 参数实现了一个 Promise 库,但使用起来很乏味 - 由于 #4,我很少需要它们.使用它们很容易出错,你很容易忘记一些事情(比如处理错误或进度事件)——就像那些手动构建和返回由 promise 回调解决的延迟的人一样,而不是调用 then.

<块引用>

异常很重,所以他们将它们用作流量控制的选择似乎很奇怪.

它们并不是真正用于控制流(如分支、循环等),而是用于异常处理:拒绝是例外.大多数 Promise 开发人员希望将它们实现为同步(阻塞)代码的替代方案 - IO 总是抛出异常,因此他们对此进行了调整.拒绝仍然被解释为异步等价于 try ... catch,尽管它们的一元性质可以以更强大的方式和更高级别的应用程序利用.

<块引用>

创建一个全新的承诺对象并返回它,只是为了拒绝它,增加了 IMO 的代码膨胀.

return new RejectedPromise(…)return reject(…)throw Error(…) 之间没有太大区别.><块引用>

如果抛出异常(例如语法错误,或者在未定义的对象上调用函数等),调试也会变得更加困难

大多数 Promise 开发人员似乎认为这是一个优势实际上 - 即使在异步代码中的(意外的)异常也会被自动捕获,因此它们可以被处理而不是炸毁程序(未被注意到).另请参阅承诺内的异常处理、抛出的错误大声"错误的可接受承诺模式?.

The specification I'm referring to is at http://promises-aplus.github.io/promises-spec/.

When using then(), you can either return a promise, and reject the promise when you desire, or you can throw an exception to reject a promise.

Why wasn't the api designed in such a fashion where for the then function, it is passed a resolve and reject function like the original promise constructor?

Exceptions are heavy in many languages (and I assume in javascript too) so it seems odd they are using them as a choice for flow control. Creating a whole new promise object and returning it, just to reject it, adds to code bloat IMO. Debugging becomes harder too in case of an exception is thrown (such as syntax errors, or if function is being called on a undefined object, etc.)

解决方案

Why wasn't the api designed in such a fashion where for the then function, it is passed a resolve and reject function like the original promise constructor?

Actually, the API in that spec emerged as a consensus amongst various implementations. However, some points that might have led to this are:

  • then is a rather functional method. It's callback only should receive one data argument, the result value of the promise.
  • Passing additional resolve/reject functions to the callback does not work well with multiple arguments or even variadic functions.
  • then is usually used as a plain mapping function. You simply return the new value, no resolve is needed.
  • When you really want to do something asynchronous in your callback where you could make use of resolve/reject, you better should use a promise anyway - which you simply can return then.

I once implemented a Promise lib with optional resolve/reject arguments, but it was tedious to use - and I seldom needed them because of #4. Using them was error-prone, you could easily forget something (like handling errors, or progress events) - just like the people who are manually constructing and returning deferreds that are resolved from promise callbacks, instead of calling then.

Exceptions are heavy so it seems odd they are using them as a choice for flow control.

They're not really meant to be used for control flow (like branching, loops etc) but for exception handling: rejections are exceptional. Most Promise developers wanted to implement them as an alternative for synchronous (blocking) code - where IO was always throwing exceptions, so they adapted this. Rejections are still explained as the asynchronous equivalent to try … catch, though their monadic nature could be utilized in mightier ways and higher-level applications.

Creating a whole new promise object and returning it, just to reject it, adds to code bloat IMO.

There's not much difference between return new RejectedPromise(…), return reject(…) and throw Error(…).

Debugging becomes harder too in case of an exception is thrown (such as syntax errors, or if function is being called on a undefined object, etc.)

Most Promise developers seem to see this as an advantage actually - (unexpected) exceptions even in asynchronous code will be caught automatically, so they can be handled instead of blowing up the program (unnoticed). See also exception handling, thrown errors, within promises and acceptable promise pattern for 'LOUD' errors?.

这篇关于为什么在 JS 中使用异常来拒绝承诺?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆