1

カスタム更新メソッドを持つリソースがあります:

angular.module('user.resources', ['ngResource']).
factory('User', function($resource) {
  var User = $resource('/user/:id', {}, {
    update: {
      method: 'PUT'
    }
  });

  User.prototype.update = function(cb) {
    console.log('foo');
    return User.update({
      id: this._id
    }, angular.extend({}, this, {
      _id: undefined
    }), cb);
  };

このリソースをスコープを介してカスタム ディレクティブに渡します。

directive('avatarUpload', function($http) {
  return {
    restrict: 'E',
    scope: {
      model: '='
    }, ...

そして、btn クリックでディレクティブ コントローラーの update メソッドを呼び出しています。

$scope.model.update(function() {
  console.log('bar');
});

私を困惑させる動作は、最初にボタンをクリックすると「foo」が表示されますが「bar」は表示されず、2回目にクリックすると「bar」が表示され、次に「foo」が表示されます。これ以上クリックすると、常に「bar」、次に「foo」が印刷されます。

PUT リクエストは、2 回目以降のクリックでのみ発生し、最初のクリックでは発生しません。

注:ディレクティブから呼び出そうとするまで、コントローラーでそのリソース更新メソッドを正常に使用してきました。私はAngular 1.1.4を使用しています。ディレクティブを異なるタイプのリソースで機能させたいので、このリソースの受け渡しを行います。

4

1 に答える 1

7

実際のコード例を見ずに断言するのは難しいですが、1.1.x シリーズ (いわゆる「不安定なブランチ」) の AngularJS を使用していると思います。もしそうなら、あなたが直面している問題は AngularJS の新機能 - バージョン 1.1.4 で導入された HTTP リクエスト インターセプター (このコミット) に関連しています。

新しく導入されたリクエスト インターセプターは$qベース (promise ベース) であり、AngularJS の世界では、promise は$digestサイクルの一部としてのみ解決されます。$digestつまり、約束を解決するには、「AngularJS の世界」(サイクル) にいる必要があります。

promise ベースのリクエスト インターセプターでは、$http呼び出しを行う前に解決する必要のある promise があります。$digest前に述べたように、この約束はサイクルに入ったときにのみ解決できます。$httpこれは、AngularJS の外部 (DOM イベント、setTimeout など) から開始する場合には発生しません。

AngularJS$resourceは に基づいて$httpいるため、上記の説明は にも適用さ$resourceれます。

したがって、上記の仮定が正しく、$resourceAngularJS の外部から呼び出しを開始していると仮定すると (カスタム ディレクティブについて話しているので、DOM イベントに賭けます) 、単に呼び出しを にラップする必要があります$resourcescope.$apply

$resource(別の応答で提案されているように)呼び出しをラップすると$timeout、問題が「修正」されます($digest ループが強制されるため、promise が解決されます)が正しいアプローチではないことに注意してください。問題は、ブラウザーが現在の JavaScript コンテキストを強制的に離れて、何もせずに再描画コンテキストに入ることです。アプリケーションが遅くなり、UI がちらつく可能性があります。

于 2013-06-24T08:47:41.480 に答える