概括:
我们在使用 Ember 应用程序时遇到了以下情况,并且正在努力寻找合适的解决方案。
我们正在处理大量数据,因此我们对数据的一些请求相当慢。
最初,我们使用 Em.RSVP.hash 将我们的请求“捆绑”在每个路由的模型挂钩中。然而,这会锁定 UI,最终是不可接受的。
我们的解决方案是在 setupController 钩子中级联请求,如下所示:
setupController: (controller, model)->
slowRequest1WhichReturnsAPromise().then (data)->
# Do something with request 1 data
slowRequest2WhichReturnsAPromise().then (data)->
# Do something with request 2 data
slowRequest3WhichReturnsAPromise().then (data)->
# Do something with request 3 data
这行得通。我们获得即时页面加载,并且可以首先显示最相关的数据。
我们试图让 Ember 保持最新(在撰写本文时为 1.11.3)。我们没有使用 Ember 数据。
问题:
问题是用户界面已解锁。例如,用户可以注销(并被重定向到登录页面)。请求持续存在并最终完成,弄乱了我们在登录和注销时设置的 csrf 令牌。下次用户尝试登录时,他们会收到 422 错误。
一个更简单的场景是在长时间运行的请求完成之前更改过滤器设置。新请求(通常通过过滤器更改缩小范围)在初始请求之前完成。然后数据被最终完成的原始请求覆盖。
我们的直接解决方案是尝试杀死未决的承诺,但找不到“现代”的方式来做到这一点。
这有效:
allPromises: []
setupController: (controller, model)->
deferredRequest1 = new Em.RSVP.defer()
# Store all promises
@get('allPromises').pushObject(deferredRequest1)
# Fire off request 1
# Spark up the next stage when request 1 finishes
deferredRequest1.promise.then ->
deferredRequest2 = new Em.RSVP.defer()
@get('allPromises').pushObject(deferredRequest2)
# ...
actions:
signOut: ->
@get('allPromises').forEach (promise)->
promise.reject('canceled')
上面的内容有点难看和简化,以了解重点。
Ember Docs 声明“新代码应该使用 RSVP.Promise 构造函数而不是(延迟)”。但是,似乎没有办法使用新方法来做到这一点。
问题:
有没有一种现代的方式来取消未决的承诺/请求?
有没有更好的方法来拆分我们的页面加载以启用一种干净的方式来取消挂起的请求?
更新
我最终使用了延迟。它并不漂亮,但在我们重构 UI 并重新考虑对慢查询的需求之前,它会起作用。
谢谢你。