Javascript 外部拒绝余烬中的未决承诺

Javascript 外部拒绝余烬中的未决承诺,javascript,ember.js,promise,rsvp-promise,Javascript,Ember.js,Promise,Rsvp Promise,摘要: 我们的Ember应用程序遇到以下情况,正在努力寻找合适的解决方案 我们正在处理大量数据,因此我们对数据的一些请求相当缓慢 最初,我们使用Em.RSVP.hash将请求“捆绑”到每个路由的模型钩子中。然而,这将锁定UI,最终是不可接受的 我们的解决方案是在setupController钩子中级联请求,如下所示: setupController: (controller, model)-> slowRequest1WhichReturnsAPromise().then (dat

摘要:

我们的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)。我们使用的不是余烬数据

问题:

问题是UI被解锁了。例如,用户可以注销(并被重定向到登录页面)。请求持续并最终完成,弄乱了我们在登录和注销时设置的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文档声明“新代码应该使用RSVP.Promise构造函数,而不是defer”。然而,似乎没有办法用新的方法做到这一点

问题:

是否有一种现代化的方式来取消待定的承诺/请求?
有没有更好的方法来分割页面负载,以实现一种干净的方式来取消挂起的请求

更新

我最终使用了延迟。它并不漂亮,但在我们重构UI,或者重新考虑慢查询的需要之前,它还是可以的

谢谢。

首先,在您的“工作”解决方案中,您没有取消注销期间的慢速查询。您只是拒绝了终止承诺链的承诺,这样就不会发送更多的请求。(当注销前的最后一个查询返回时,它仍然可以改变您的cookie。)

如果这已经为您所接受,那么您需要做的是在承诺链中插入可识别签出的检查,以便在用户已签出时立即终止

didSignOut: false

setupController: (controller, model) ->
    slowRequest1WhichReturnsAPromise().then ->
        return null if didSignOut
        slowRequest2WhichReturnsAPromise().then ->
            return null if didSignOut
            slowRequest3WhichReturnsAPromise().then ->
                return null if didSignOut
                // ...
行动: 签出:-> @set('didSignOut',true)


返回空值
可以替换为下一步要执行的任何操作。如果希望以集中方式处理此事件,仍然可以通过第二个参数
.then()
拒绝承诺,并为其设置
RSVP.on(“error”,…)
处理程序。

是的,有些现代承诺库支持正确的取消。然而,
RSVP
似乎不是其中之一。