web-dev-qa-db-ja.com

angular.js $ httpサービスを遅延させる

私はいくつかのangular以下のようなレガシーASP.NET .asmx Webサービスに対してajax呼び出しを行うためのファクトリーを持っています:

module.factory('productService', ["$http",
function ($http) {
    return {
        getSpecialProducts: function (data) {
            return $http.post('/ajax/Products.asmx/GetSpecialProducs', data);
        }
    }
} ]);

ローカルネットワークでテストしているので、応答時間は「長すぎます」。不正な接続をシミュレートするために呼び出しを行ってから数秒で$ httpを遅延させるスマートな方法はありますか?

それとも、ファクトリメソッドへのすべての呼び出しを$ timeoutでラップする必要がありますか?

$timeout(function() {
  productService.getSpecialProducs(data).success(success).error(error);
}, $scope.MOCK_ajaxDelay);
34
Cotten

興味深い質問です!

自分で言ったように、$timeoutは遅延呼び出しの最も論理的な選択肢です。どこでも$timeoutを呼び出す代わりに、 documentation of $http で概念的に概説されているように、$timeout promiseに$http promiseをラップする応答インターセプターをプッシュし、構成ブロックの1つに登録できます。これは、すべての$http呼び出しが$timeout遅延の影響を受けることを意味します。以下の線に沿ったもの:

$httpProvider.interceptors.Push(function($timeout) {
    return {
        "response": function (response) {
            return $timeout(function() {
                return response;
            }, 2500);
        }
    };
});

あなたの「悪い接続をシミュレートすること」へのボーナスとして、あなたは拒否するか、ランダムに全く何もしないこともできます。 Heh heh heh。

53
Steve Klösters

新しいchromeデバイスエミュレーターには、ネットワーク調整機能があります。

enter image description here

アクセスするには:Google Chromeで、F12を押して開発者ツールを開きます。次に、左上の[デバイスモードの切り替え]アイコン([要素]メニューの左)をクリックします。

16
Vinz243

@stevuuの答えをさらに発展させる

responseInterceptorsは非推奨のようです(1.2.20時点)。interceptorsメカニズムで動作するようにコードを変更しました。

$httpProvider.interceptors.Push(function($q, $timeout) {
    return {
        'response': function(response) {
            var defer = $q.defer();
            $timeout(function() {
                        defer.resolve(response);
                }, 2300);
            return defer.promise;
        }
    };
});
4
Vladius

Defer()。promiseパターンに$ qサービスを使用できます。

function someFunction(MOCK_ajaxDelay) {
   var deferred = $q.defer();
   $http.post('/ajax/Products.asmx/GetSpecialProducs', data).success(function(response) {
      $timeout(function() {deferred.resolve({ success: true, response: response })}, MOCK_ajaxDelay);  
   }).error(function() {
      $timeout(function() {deferred.resolve({ success: true, response: response } }, MOCK_ajaxDelay);  
   });
   return deferred.promise;
}

someService.someFunction(500).then(function(data) {
    if (data.success) {
      $scope.items = data.response.d;
    }
});

ただし、実際に模擬テストを行う場合は、ngMockを調べることをお勧めします。 http://docs.angularjs.org/api/ngMock 。$ httpBackend

3
Noogen

@ stevuu's answerは正しいですが、それ以降の新しいAngularJSバージョンでは構文が変更されています。更新された構文は次のとおりです。

$httpProvider.interceptors.Push(["$q", "$timeout", function ($q, $timeout) {
  function slower(response) {
    var deferred = $q.defer();
    $timeout(function() {
        deferred.resolve(response);
    }, 2000);
    return deferred.promise;
  }
  return {
    'response': slower
  };
}]);
2
Pratyush

Promise apiを$ timeoutと組み合わせて使用​​して、これを実現できます。 $ http.post関数は、.successおよび.error(これらはhttp固有のメソッドです)を呼び出すことができるpromiseを返します。 httpリクエストが完了すると、この約束はresolvedになります。独自のプロミスを作成する場合、2秒遅らせて、httpリクエストが完了したときに解決するように指示できます。

module.factory('productService', function ($http, $q, $timeout) {

    return {
        getSpecialProducts: function (data) {
            var defer = $q.defer();
            $http.post('/ajax/Products.asmx/GetSpecialProducs', data).success(
              function(data) {
                // successful http request, resolve after two seconds
                $timeout(function() {
                    defer.resolve(data);
                }, 2000)
            }).error(function() {
                defer.reject("Http Error");
            })
            return defer.promise;
        }
    }

});

ただし、promise.then(successCallback, errorCallback)機能を使用する必要があります。つまり、defer.resolve({})に渡されたオブジェクトに明示的に指定しない限り、コントローラー/ディレクティブからhttpヘッダー、ステータス、構成にアクセスできなくなります。

リンク:

0
Ian Haggerty

約束を返すサービスを使用している場合は、$ timeoutの前にreturnも配置する必要があります。

return dataService.loadSavedItem({
    save_id: item.save_id,
    context: item.context
}).then(function (data) {
    // timeout returns a promise
    return $timeout(function () {
        return data;
    },2000);
});

それが誰かを助けることを願っています!

0
Ferenc Takacs

質問のテストの側面に応えて、 Fiddler には、遅延をシミュレートする必要があるときに役立つ非常に便利な機能があります。

  1. Fiddlerの[AutoResponders]タブをクリックします。
  2. 遅延するリクエストのURLに一致する正規表現を含むルールを追加します。
  3. 「応答」を「* delay:1000」に設定します。数値はミリ秒単位の遅延です。

FiddlerのAutoResponder機能は、多くのhttp要求を含むJSをテストするのに非常に役立ちます。特定のhttpエラーコード、ブロック応答などで応答するように設定できます。

0
Co7e