创建后的Ember数据编辑"错误:在状态root.loaded.updated.uncommitted中尝试在<app @ model:...>上处理事件`didCommit`

Gab*_*ant 6 race-condition ember.js ember-data emberfire

tl; dr:在模型保存正式不支持的情况下编辑模型的属性?我似乎记得,在大约2013年,国家机器拒绝了在记录处于飞行状态时进行编辑的尝试,但我认为该限制已被删除.它不再抛出状态机错误......它似乎只会导致错误:/


在我正在处理的应用程序中,按Enter键创建一个新条目并聚焦标题字段,让用户立即开始输入.对该字段的更改将通过去抖动保存自动保留.通常这很好用,但如果我开始输入太快,我会收到以下错误:

Attempted to handle event `didCommit` on <app@model: ...> while in state root.loaded.updated.uncommitted.
Run Code Online (Sandbox Code Playgroud)

(我在底部包含了完整的错误和追溯[1])

该记录看起来似乎已经正确地保存到服务器(Firebase通过EmberFire适配器),但是从那时起该应用程序还有其他奇怪之处(可能是因为运行循环的迭代在完成之前爆炸).

为了了解情况,我将观察者附加到模型currentState.stateNametitle字段上.对于无错误的创建和保存,记录将通过以下状态:

      [Press Enter; Pause]
               |
               V
 root.loaded.created.uncommitted
               |
               V
<title observer fires with blank>
               |
               V
   root.loaded.created.inFlight
               |
               V
       root.loaded.saved
               |
               V
        [Type in title]
               |
               V
root.loaded.updated.uncommitted
               |
               V
<title observer fires with value>
               |
               V
  root.loaded.updated.inFlight
               |
               V
       root.loaded.saved
Run Code Online (Sandbox Code Playgroud)

出现错误时,过程如下所示:

 [Press Enter & type immediately]
               |
               V
 root.loaded.created.uncommitted
               |
               V
<title observer fires with blank>
               |
               V
   root.loaded.created.inFlight
               |
               V
[title observer fires with value]
               |
               V
       root.loaded.saved
               |
               V
root.loaded.updated.uncommitted
               |
               V
        <Error appears>
               |
               V
  root.loaded.updated.inFlight
               |
               V
       root.loaded.saved
Run Code Online (Sandbox Code Playgroud)

我最初的想法是错误是由初始创建完成之前的第二次保存引起的,但错误发生在root.loaded.updated.uncommitted- 记录进入之前root.loaded.updated.inFlight.我很确定这意味着问题是由字段的实际编辑引起的,而不是save()对记录的调用.

编辑:确实,完全删除标题的保存似乎没有任何影响.这似乎表明问题确实源于编辑领域.

看一下追溯(下面),导致didCommit事件的原因并不明显.我在想,如果我的问题是余烬的调用故障didSaveRecord()而模型是在错误状态,但搜索代码库余烬任何电话不转达到didSaveRecord()任何这样就不会似乎是问题.

这只是Ember Data的设计行为吗?如果是这样,它似乎是一个非常严重的限制,我没有在任何地方提到过.[2]

在某一点上,ED用于防止在记录处于飞行状态时设置属性,但我认为该限制已被删除(并且它并未明确阻止我像以前那样这样做).

我想到的第一个解决方法是缓冲对字段的写入,直到模型处于"可写"状态......除了我从未见过任何官方Ember示例那样做.

这是正确的(或至少是合理的)解决方案吗?

如果是这样,什么构成"可写"状态?还有什么inFlight?(我可以用isSaving旗子检查一下,对吧?)

如果没有,是否有其他官方推荐的模式来处理这个问题?

编辑:

在阅读有关自动保存的旧帖子时,我遇到了一篇文章,其中提到了一个缓冲代理模式(最后一个主要部分:"给我们的属性一个缓冲区")听起来与我所描述的非常类似.这与Luke Melia从2013年开始的示例代码相关联,Stefan Penner称他们"经常"使用(当时).这两者都是Ember社区的积极贡献者,所以我会把它作为有效的"官方"建议,但问题仍然存在:三年后这仍然是建议的方法吗?

编辑:

该代理模式现在打包为ember-buffered-proxy Ember CLI插件,但它的README仍然没有真正提到何时可能需要这种模式(这似乎暗示它在需要该功能的特定场景中偶尔有用,而不是修复了Ember Data的核心限制)


[1]完整错误/追溯:

ember.debug.js:31352 Error: Attempted to handle event `didCommit` on <app@model:task::ember965:-KLmwiGUhqrUW_CiRGb4> while in state root.loaded.updated.uncommitted. 
    at new Error (native)
    at Error.EmberError (http://app.localtest.me:4200/assets/vendor.js:25781:21)
    at InternalModel._unhandledEvent (http://app.localtest.me:4200/assets/vendor.js:82039:13)
    at InternalModel.send (http://app.localtest.me:4200/assets/vendor.js:81917:14)
    at InternalModel.adapterDidCommit (http://app.localtest.me:4200/assets/vendor.js:82220:12)
    at didSaveRecord (http://app.localtest.me:4200/assets/vendor.js:89092:21)
    at http://app.localtest.me:4200/assets/vendor.js:89814:15
    at Object.Backburner.run (http://app.localtest.me:4200/assets/vendor.js:10788:25)
    at _adapterRun (http://app.localtest.me:4200/assets/vendor.js:89648:31)
    at http://app.localtest.me:4200/assets/vendor.js:89805:13
onerrorDefault  @   ember.debug.js:31352
exports.default.trigger @   ember.debug.js:52095
(anonymous function)    @   ember.debug.js:53346
Queue.invoke    @   ember.debug.js:333
Queue.flush @   ember.debug.js:397
DeferredActionQueues.flush  @   ember.debug.js:205
Backburner.end  @   ember.debug.js:560
(anonymous function)    @   ember.debug.js:1126
Run Code Online (Sandbox Code Playgroud)

[2]只有2 3 4提到的,我碰到过类似的问题:

  1. 在第一个保存请求仍在进行时发出第二个保存请求的情况.在这种情况下,通过去除保存来解决问题,但我已经这样做,并且如果模型保存已在进行中(通过显式检查isSaving属性),则重新排队保存.并且,正如我之前所说,甚至完全摆脱后标题更改自动保存似乎没有效果.
  2. 突变数据的一个内的情况下DS.Transformserialize()方法
  3. 这看起来可能是同样的问题,而且是在一个旧的情况下Routemodel()挂钩,它是简单的等待保存完成后再继续.
  4. 另一个在inFlight导致无效状态转换时设置属性的较旧示例.首先,这不会再导致相同的错误.其次,提供的唯一解决方案是切换到Ember Persistence Foundation,该基金会似乎在2014年中期废弃(编辑:已确认)