Javascript Angularjs$http等待响应

Javascript Angularjs$http等待响应,javascript,asynchronous,angularjs,angularjs-directive,promise,Javascript,Asynchronous,Angularjs,Angularjs Directive,Promise,我是javascript/angularjs的新手。我想在某些元素上完成鼠标悬停时显示一个引导弹出框 我为此制定了一个指令 (function(angular, app) { app.directive('popOver',["$window","$http",function($window,$http){ return function(scope,elem,attrs){ elem.on('mouseover',function(){ console

我是javascript/angularjs的新手。我想在某些元素上完成鼠标悬停时显示一个引导弹出框

我为此制定了一个指令

(function(angular, app) {
  app.directive('popOver',["$window","$http",function($window,$http){
    return function(scope,elem,attrs){
      elem.on('mouseover',function(){
        console.log('mouseover');
        var data = scope.$apply(attrs.popOver);
        console.log('in directive again');
        console.log(data);
      });
    };
  }]);
})(angular, app);
指令的值是一个函数

name

函数vcard(id)在我的angularjs控制器中定义。它检查数据是否已经存在于localstorage中,如果存在,则返回数据。否则,它将执行$http get请求并将数据存储在localstorage中

$scope.getVCard = function(id){

  var vcardKey = vcardKeyPrefix+id;

  var vCardFromLS = localStorageService.get(vCardKey);
  if(vCardFromLS){
    return localStorageService.get(vCardKey);
  }

  $http.get(app.common.vcardUrl(id)).
    success(function(data){
      localStorageService.set(vCardKey,data);
    }).
    error(function(error){
      F1.common.error(data,function(){});
    });

    return localStorageService.get(vCardKey);
};
由于$http返回PROMITE,我在指令中得到一个值undefined。如何确保函数
getVCard
同步返回

在谷歌搜索之后,我看到了很多结果。但建议的想法是使用回调。但我不确定回调将如何实现同步。感谢您的帮助

更新1(回应Foo L的评论)
我计划在多个地方使用相同的指令。用于vCard和产品信息等的弹出窗口。唯一不同的是pop-over指令的参数。这样的话,指令就只需要显示弹出窗口。获取数据的位置将在传递给指令的单独函数中

您不能强制
$http.get()
同步。由于
$http.get()
不可避免地是异步的,因此只能返回值的承诺,而不能返回值本身

由于在调用
$http.get()
时需要执行此操作,因此还必须在另一个条件下返回承诺-当从本地存储成功检索
vCardFromLS
时。这确保返回到
$scope.getVCard()
的任何调用的对象都有一个
.then()
方法,即它是一个承诺,无论是否调用了
$http.get()

所以代码应该是这样的:

$scope.getVCard = function(id) {
    var vcardKey = vcardKeyPrefix + id;
    var vCardFromLS = localStorageService.get(vCardKey);
    var dfrd = $q.defer();
    if(vCardFromLS) {
        dfrd.resolve(localStorageService.get(vCardKey));
    }
    else {
        $http.get(app.common.vcardUrl(id)).success(function(data) {
            localStorageService.add(vCardKey, data);//.add() rather than .set() ?
            dfrd.resolve(data);
        }).error(function(error) {
            F1.common.error(data, function() {
                dfrd.reject('$http.get(app.common.vcardUrl(id)) failed');
            });
        });
    }
    return dfrd.promise;
};
现在,您需要确保对
$scope.getVCard()
的响应得到适当处理,例如:

$scope.getVCard(id).then(function(data) {
    //success - do whatever is required with data
}, function(reason) {
    //failure - log and/or display `reason` as an error message
})
编辑:

我的“…你必须在其他条件下还承诺…”是言过其实

我应该说,“…你可以,为了简单起见,在其他条件下回报一个承诺……”


另一种可能性是根据是否返回了承诺或其他类型的对象/值进行分支。但是,这很混乱,通常会导致一些代码重复。

将函数和id分别传递到指令中怎么样?您可以使用id作为参数调用函数,并设置一个
作用域。$watch
,当它成功返回时将触发它。我计划在多个位置使用相同的指令。用于vCard和产品信息等的弹出窗口。唯一不同的是pop-over指令的参数。这样,指令就不得不费心于只显示弹出窗口。获取数据的位置将在一个单独的函数中,该函数将传递给指令。请使用。@Stewie你能帮我举个例子吗?我不清楚我们如何用ui-bootstrap做到这一点。这太棒了!无论数据是否在本地存储中可用,我从未想过要返回承诺。