34

我有一些角度工厂,用于对遗留 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);
4

8 回答 8

53

有趣的问题!

正如您自己提到的,$timeout对于延迟通话来说,这是最合乎逻辑的选择。$timeout您可以推送一个响应拦截器,该响应拦截器将 Promise 包装在$http Promise 中,而不是到处调用,正如文档中$timeout概念性地概述的那样,并将其注册到您的配置块之一中。这意味着所有呼叫都会受到延迟的影响。类似于以下内容:$http$http$timeout

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

作为您“模拟不良连接?”的奖励,您也可以随机拒绝或完全不做任何事情。嘿嘿嘿。

于 2013-08-14T17:45:43.907 回答
16

新的 chrome 设备模拟器具有网络节流功能:

在此处输入图像描述

到达那里:在谷歌浏览器中,按 F12 打开开发者工具。然后,在左上角,单击“切换设备模式”图标(“元素”菜单左侧)。

于 2014-10-20T12:06:56.300 回答
4

在@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;
        }
    };
});
于 2014-09-05T14:38:58.897 回答
3

您可以将 $q 服务用于 defer().promise 模式:

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

于 2013-08-14T17:48:52.420 回答
2

虽然@stevuu 的回答是正确的,但从那时起,新的 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
  };
}]);
于 2015-08-07T08:49:12.003 回答
0

您可以使用 promise api 和 $timeout 来实现这一点。$http.post 函数返回一个 Promise,您可以从中调用 .success 和 .error (这些是 http 特定的方法)。当 http 请求完成时,此承诺将得到解决。如果您构建自己的承诺,那么您可以告诉它延迟 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)功能 - 也就是说,除非您明确将它们提供给传递给的对象,否则您将无法从控制器/指令访问 http 标头、状态和配置defer.resolve({})

链接:

于 2013-08-14T18:07:56.110 回答
0

针对您问题的测试方面,Fiddler有一个非常有用的功能,可以在您需要模拟延迟时提供帮助:

  1. 单击 Fiddler 中的 AutoResponders 选项卡。
  2. 使用与您要延迟的请求的 URL 匹配的正则表达式添加规则。
  3. 将“respond with”设置为“*delay:1000”,其中数字是以毫秒为单位的延迟。

Fiddler 中的 AutoResponder 功能对于测试涉及大量 http 请求的 JS 非常有用。您可以将其设置为响应特定的 http 错误代码、阻止响应等。

于 2013-11-27T17:51:30.773 回答
0

如果您正在使用返回承诺的服务,那么在内部您也应该在$timeout之前放置一个返回,因为这只是返回另一个承诺。

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

希望它可以帮助某人!

于 2015-07-08T18:00:56.410 回答