概要:
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 Data は使用していません。
問題:
問題は、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 Docs には、「新しいコードは (遅延の) 代わりに RSVP.Promise コンストラクターを使用する必要がある」と記載されています。ただし、新しい方法を使用してこれを行う方法はないようです。
質問:
保留中の約束/要求をキャンセルする最新の方法はありますか?
保留中のリクエストをクリーンな方法でキャンセルできるように、ページの読み込みを分割するより良い方法はありますか?
アップデート
私は延期を使用することになった。美しくはありませんが、UI をリファクタリングし、おそらく遅いクエリの必要性を再考するまでは十分でしょう。
ありがとうございました。