問題タブ [zonejs]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票する
0 に答える
511 参照

angular - NgZone がこの問題を解決するのはなぜですか?

ユーザーが自分の Google アカウントを介して自分自身を識別できるアプリケーションを作成しています。舞台裏では、gapi を使用してログインを処理しています。一方、ユーザーObservableの状態(オンライン/オフライン)が変化するたびに加入者に情報をブロードキャストする「ユーザー」と呼ばれる角度のあるサービスがあります。次に、すべてを結合するためにボタンがあり、ユーザーがそれをクリックすると、次のようになります。

  • gapi が初期化されると解決される promise が作成されます。(以下のコードの 1 行目)
  • promise が解決されると、gapi を介して Google ログインが実行されます。(以下のコードの 2 行目)
  • ログインの約束が解決されると、AJAX リクエスト ID がバックエンドに対して行われ、Google トークンが検証され、電子メール、名前などの情報が返され、このオブザーバブルにサブスクライブされます。this.restService(以下のコードの で始まる行)
  • 上記のオブザーバブルが Web サービスによって返された値を発行するとき、ユーザーのステータスのオブザーバブルの値を発行する「ユーザー」サービスの関数を呼び出します (ユーザーが現在認証されているという事実をブロードキャストします)。
  • 次に、すべてのサブスクライバーがこの情報を受け取り、ユーザーがログインしていることを認識します。

コードは次のとおりです。

問題は、コードが機能する場合と機能しない場合があることです。調査の結果、これは Web サービスの実行時間に関連していることに気付きました。これを確実にするために、リクエストの実行を2秒間一時停止するステートメントを内部に作成しました。その場合、コードは常に失敗します。しかし、「失敗」とはどういう意味ですか?

ページのどこかに、ユーザー サービス オブザーバブルにサブスクライブするコンポーネントがあります。

Web サービスが非常に高速に実行されると、 が表示されconsole.logcanPostCommentプロパティが更新され、ビューも更新されるため、問題はありません。ただし、Web サービスに少し時間がかかるconsole.logと、正しい値が表示されますが、ビューは更新されません...

Angular の変更検出と関係があるのではないかと疑って、次のようにゾーンを使用します。

そして、それは機能します...だから、ゾーンについて読んで、変更検出(またはそのようなもの...)を実行する必要があることをangularに警告するために使用されていることを知りましたが、setTimeoutまたはAJAX呼び出しのような一般的な機能も読みましたすでに「ゾーン」によってモンキーパッチが適用されているため、問題がどのように解決されるのかわかりません。また、この問題が発生する理由もわかりません。canPostCommentAngularが変更を認識しないのはなぜですか?

私のコードは少し複雑なので、それを plunkr するのはかなり難しいでしょう。そのため、関連するコードのほとんどをコピーして貼り付けます。

編集

質問した後、ログイン プロセス全体がいつ完了したかを知る必要があったため、コードを少し変更する必要がありました。実際、ユーザーがログイン ボタンをクリックすると、そのキャプションが「Logging in...」になり、プロセス全体が完了すると消えます。オブザーバブルを購読することuserService.getStatusもできましたが、次のことができるという約束をすることにしました。

したがって、上記のコードを次のように更新しました。

好奇心から、this.zoneService.run何が起こるかを確認するためだけにステートメントを削除しようとしましたが、それがなくても機能することがわかりました...すべてを約束に入れると問題が解決するようです...しかし、問題はまだ残っています...なぜ最初の例は機能しませんでしたか?