免责声明:这里有两个问题,但我觉得它们密切相关。
我正在尝试将promise对象传递给指令,并且我希望在promise解析后立即在指令中运行一些初始化代码。
在控制器中我有:
$scope.item = $http.get(...)
.success(function (result) {
$scope.item = result.item;
});
$scope.item
传递给指令(通过名为item
的隔离范围中的属性)。
指令链接函数最终执行如下操作:
Promise.resolve(scope.item)
.then(function () {
initialize();
});
这在Firefox中工作正常,但是当我在IE上运行时,我收到错误,因为没有定义Promise。这个问题让我意识到我需要使用AngularJS $ q服务以提供浏览器之间的一致性,当我查看文档时,我发现了另一个问题,一开始看起来很小但实际上让我头疼:{ {1}}函数已弃用,我应该使用success()
代替。我想,很轻松,但是一旦我在控制器中更改then(successCallback)
调用,代码就会停止在Firefox中运行!我无法弄清楚为什么。所以这是第一个问题。
第二个问题是(即使我将成功调用留在控制器中)如果我修改指令链接函数中的代码以使用$ q与我认为相同的东西:
success
这根本不起作用。有什么建议吗?
答案 0 :(得分:4)
您需要使用Angular的$q
,不仅因为它适用于各种浏览器,还因为它是deeply linked to Angular's digest cycles。其他承诺库can accomplish this feat但本机承诺不能轻易做到。
$q.when
做什么({q}版本的Promise.resolve
)将值或承诺转换为$q
承诺。您不需要这样做,因为您已经使用了Angular自己的$http
API,它已经返回了承诺。
我热烈建议您将您的网络电话放在服务中,不要直接影响范围 - 然后调用这些服务来更新范围。
模式基本上是:
$http.get(...) // no assign
.success(function (result) { // old API, deprecated
$scope.item = result.item; // this is fine
});
或者使用has the benefits of promises over callbacks更好的then
承诺API,以及链接和错误处理:
$http.get(...).then(function (result) {
$scope.item = result.data;
});
答案 1 :(得分:0)
您对弃用的.success
方法是正确的。 .then
方法返回的数据与.success
方法不同。
$scope.httpPromise = $http.get(...)
.then(function (result) {
$scope.item = result.data.item;
return result.data;
});
您需要将数据>>返回 链。
$scope.httpPromise.then ( function (data) {
//Do something with data
initialize();
});
有关弃用.success
方法的详细信息,请参阅AngularJS $http Service API Reference -- deprecation notice。
答案 2 :(得分:-1)
由于scope.item是一个承诺,你所要做的就是:
scope.item.resolve.then(function() { initialize(); });
确保在你的指令中注入$ q。
答案 3 :(得分:-1)
改进答案
正如@ benjamin-gruenbaum所说,我在答案中使用了反模式。因此,解决方案基本上是将承诺传递给您的指令并在那里使用(如Benjamins的答案中所述)。
工作jsFiddle:https://jsfiddle.net/eovp82qw/1/
旧答案,使用反模式
很抱歉,如果我给你的解决方案可能与你的代码差别太大。但也许你可以将它用于你的解决方案。
我的方法是创建第二个承诺,我将其移交给您的指令。这是解决指令等待状态的一种更简洁的方法,不会为两个不同的任务重用相同的范围变量。
<强> HTML 强>
<body ng-app="myApp">
<div ng-controller="MyCtrl">
<my-directive promise="promiseFromController"></my-directive>
</div>
</body>
<强> JS 强>
function MyCtrl($scope, $q, $http) {
function init() {
var deferredCall = $q.defer();
// simulated ajax call to your server
// the callback will be executed async
$http.get('/echo/json/').then(function(data) {
console.log('received', data);
deferredCall.resolve(data); //<-- this will resolve the promise you'll handover to your directive
});
// we're return our promise immediately
$scope.promiseFromController = deferredCall.promise;
}
init();
}
angular.module('myApp',[])
.controller('MyCtrl', MyCtrl)
.directive('myDirective', function() {
return {
scope: {
promise: '='
},
controller: function($scope) {
console.log($scope);
$scope.promise.then(function(data) {
console.log('received data in directive', data);
});
}
}
})
工作jsFiddle:https://jsfiddle.net/1ua4r6m0/ (没有输出,请检查浏览器控制台;))