Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/419.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何测试延迟的角度承诺?_Javascript_Angularjs_Unit Testing_Promise_Angular Promise - Fatal编程技术网

Javascript 如何测试延迟的角度承诺?

Javascript 如何测试延迟的角度承诺?,javascript,angularjs,unit-testing,promise,angular-promise,Javascript,Angularjs,Unit Testing,Promise,Angular Promise,我如何用模拟的角度和一段时间后解决的承诺运行测试 简单地说:下面的测试永远不会运行 var injector=angular.injector(['ngMock']); var scope=injector.get(“$rootScope”)。$new(); var q=injector.get(“$q”); var promise=函数(){ 返回q(函数(解析、拒绝){ setTimeout(函数(){ 解决(); }, 500); }); }; 允诺 .然后(函数(){ document

我如何用模拟的角度和一段时间后解决的承诺运行测试

简单地说:下面的测试永远不会运行

var injector=angular.injector(['ngMock']);
var scope=injector.get(“$rootScope”)。$new();
var q=injector.get(“$q”);
var promise=函数(){
返回q(函数(解析、拒绝){
setTimeout(函数(){
解决();
}, 500);
});
};
允诺
.然后(函数(){
document.getElementById('result').innerHTML='testrun';
});
//兑现承诺
范围。$digest()


开始测试…

很明显,
$q
与$rootScope.Scope模型观察机制以角度方式集成,这意味着分辨率或拒绝更快地传播到模型中,并避免不必要的浏览器重新绘制,这将导致UI闪烁。(有关更多详细信息,请检查中Q和$Q之间的差异)。我刚刚在您的代码片段中添加了
范围。$apply()

var injector=angular.injector(['ngMock']);
var scope=injector.get(“$rootScope”)。$new();
var q=injector.get(“$q”);
var promise=函数(){
返回q(函数(解析、拒绝){
setTimeout(函数(){
解决();
作用域:$apply();
}, 500);
});
};
允诺
.然后(函数(){
document.getElementById('result').innerHTML='testrun';
});
//兑现承诺
范围。$digest()


开始测试…

因此,您不应该将
设置超时
功能用于angular,而可以使用angular提供的
$timeout
服务。在单元测试中,超时之类的事情将无法像在页面中那样有效地计算和控制。为了解决超时问题,您可以使用
$timeout.flush()
,而是这样做:

var injector = angular.injector(['ngMock']);
var scope = injector.get('$rootScope').$new();
var q = injector.get('$q');
var timeout = injector.get('$timeout');

var promise = function() {
  return q(function(resolve, reject) {
    timeout(function() {
      resolve();
      scope.$apply();
    }, 500);
  });
};

promise()
  .then(function() {
    document.getElementById('result').innerHTML = 'TEST RUN';
  });

//resolve the promises
timeout.flush();
scope.$digest();
好的,我知道了

这个解决方案实际上是@mido22提出的,但我更喜欢一个稍微不同的版本,您可以从$scope和inprog的文档中得到它

根据,当您在异步函数中工作时,需要调用$apply(),比如,它明确地说,setTimeout。 更好的解释是:

直接作为从DOM或第三方库回调某个外部事件而触发的代码应该期望它永远不会从Angular内部调用,因此它调用的任何Angular应用程序代码都应该首先包装在对$apply的调用中。”

因此,解决方案是将影响Angular的所有调用(包括resolve()和reject())封装到$apply中

为了避免inprog错误,不能在另一个内部调用$apply()。本例中不是这样,但是,假设我们有另一个嵌套的setTimeout,只有最后一个被调用的应该调用$apply()

更新

根据,避免inprog错误的最佳方法是将非角度代码包装在$timeout()中。这是angular的人推荐的策略

var injector=angular.injector(['ngMock']);
var scope=injector.get(“$rootScope”)。$new();
var q=injector.get(“$q”);
var promise=函数(){
返回q(函数(解析、拒绝){
setTimeout(函数(){
作用域$apply(函数(){
解决();
});
}, 500);
});
};
允诺
.然后(函数(){
document.getElementById('result').innerHTML='testrun';
});


开始测试…

您是否需要让超时实际运行500毫秒(或者可以是1毫秒1000000毫秒?),或者只是从超时开始计算,然后让承诺得到解决?超时只是一个例子,事实上,可以使用$timeout而不是setTimeout轻松解决它。问题是,无论何时异步使用$q,除非知道何时调用作用域,否则无法对其进行测试。$digest();这并不总是事先知道的。为什么你要用angular测试非角度代码?因为我正在制作一些非角度代码,角度友好。具体地说,我正在将Cordova插件与Ionic集成。我已经检查了这些人在中做了什么,他们还使用了$q承诺(请参阅a)。在他们的测试中,他们确实调用了
$rootScope.$digest();
(请参阅),但这在我的情况下不起作用:(谢谢你的建议,但我认为这是不可接受的,原因有两个:1)函数“promise”是正在测试的函数,不应该将其逻辑与测试的逻辑混在一起;2)我在代码中尝试过这种方法,我得到了一个errors@dariosalvi您得到的是inprog错误,因为它(
scope.$apply();
)是不安全的,一种方法是在执行之前检查状态,另一种方法是使用浏览器的默认承诺(它是polyfill for!@#类似IE),在这里使用$q有什么特别的原因吗?我之所以使用$q,是因为它是标准的angular promise实现,不需要导入任何其他东西,也不必担心不同的API。也许,在模拟时,你不能这样使用$q,这对可测试性有点不利。谢谢你的建议。正如我在第一篇评论中所说,timeout只是一个例子,我知道我可以使用$timeout,但这不是我的观点。我的观点是:当我有一些异步代码时,如何使用$q进行测试?具体地说,在我的具体案例中,我有一组对Cordova插件的调用,所以没有角度$-我可以使用的东西。