我是否应该改变一个已承诺并已解决的值的内部状态

Should I mutate internal state of a value that was promised and is already resolved?

本文关键字:承诺 状态 解决 一个 内部 是否 改变      更新时间:2023-09-26

代码示例(可变性)

.factory('objSingleton', function ($q) {
  var o = {a: 1}
  setTimeout(function () {
    o.a = 2
  }, 1000)
  return $q.when(o)
})

另一种选择是(不变性)

.factory('objFactory', function ($q) {
  var promise = $q.when({a: 1})
  setTimeout(function () {
    promise = $q.when({a: 2})
  }, 1000)
  return function () {
    return promise
  }
})

问题

我希望听到"赞成"answers"反对"的声音,以帮助我决定是接受承诺还是不接受承诺(在创建+返回承诺的API中)。

注意:代码示例使用AngularJS风格的依赖项注入器,但问题和答案适用于任何和所有使用promise的JS环境

承诺不应在做出此决定时发挥任何作用

毕竟,承诺只是对可能需要时间的计算的抽象。承诺的结果是对正常结果的抽象。

通常,具有不可变的值是一种很好的做法,因为可变状态无论如何都有是非常糟糕的。可变状态使测试更加困难。在您的情况下,可变全局状态甚至更糟。Angular的作者米斯科·哈维里写了一篇关于为什么的最好的文章,名为《单身汉是病态的骗子》。

所以,答案是——做同步代码中应该做的事情。您会在同步代码中返回一个副本或引用吗。这是一个我无法真正回答的主观问题,但所有事实都指向";在您的代码中具有尽可能少的状态";。

我非常不同意你的意见。该框架在这一决定中发挥着重要作用。在angular中,如果将解析值附加到一个或多个范围,然后更改解析值,则angular将自动更新所有相关视图。我认为这是angular的一个主要特征,所以我确实改变了我决心的promise值。

如果您返回一个新的promise,您需要自己$watch值,并负责视图的任何更新。正因为如此,我不喜欢使用不可变的值。

在其他框架中,它可能不会以同样的方式工作,这个问题可能会有另一个答案。

Promise结果值肯定应该被认为是不可变的。

承诺确实促进了函数式编程风格,解决这些问题将永远解决它们的价值。他们的约定是,无论何时发生,他们都将调用具有完全相同值的所有回调。您不应该仅仅将其视为对象身份,还应该将其视为由对象"状态"。

不改变结果值将导致更干净、更不容易出错的代码 甚至还有promise库通过Object.freeze对解析值进行强制执行

这种方法的唯一缺点是,对对象进行必要的克隆会慢得多。然而,如果您可以绝对确定除了您之外没有其他人使用这些值,则可以对对象进行变异。

在我个人看来,angular确实对此过于宽容,但这种突变的自动传播是他们的设计。