如何将 Promise 分配给作用域

12
如何将$promise分配给$scope.advertiserName?在下面的示例中,Console.log($scope.title)返回“undefined”。
如何将$promise分配给$scope.advertiserName?在下面的示例中,Console.log($scope.title)返回“undefined”。
 Restangular.all('advertiser').one("?id=" + 1).getList().then(function(data) {
   $scope.advertiserName = data.name;
   $scope.advertiserId = data.id;
 });

 $scope.title = $scope.advertiserName;
 $scope.id = $scope.advertiserId;

现在甚至都不清楚你在问什么。你想将$promise赋值给advertiserName吗?目前来看,你已经正确地将结果赋值给了advertiserName;问题出在哪里呢? - Mike Perrenoud
4个回答

3
我们可以使用回调函数来在获取ajax调用的响应后执行代码行。您可以访问这个博客,了解关于回调函数的精彩解释 http://javascriptissexy.com/understand-javascript-callback-functions-and-use-them/。 让我们通过代码来理解它。
    $scope.setNameId = function (title,id,callBackFunction) {
     Restangular.all('advertiser').one("?id=" + 1).getList().then(function(data) {
      // $scope.advertiserName = data.name;
       $scope.title= data.name;
      // $scope.advertiserId = data.id;
       $scope.id=data.id;
       callBackFunction();
     });
    }
     $scope.setNameId($scope.title,$scope.id,executeAfterResponse);
    var executeAfterResponse=function(){
    //code that you want to execute when value of $scope.title and $scope.id has changed
    };

我们也可以通过这种方法来做到它

$scope.setNameId(executeAfterResponse);

如果不将$scope.title$scope.id变量作为参数传递给$scope.setNameId函数,可以直接在同一文件中访问$scope变量。

由于我们直接为$scope.name$scope.id赋值,因此注释掉的代码行不是必需的。


1
在下面的示例中,您期望维护advertiserName和title和advertiserId和id的内存引用。但是,在从作用域中获取属性时,它是按值而不是按引用检索的。如果您想让您的代码工作,您需要执行以下两个操作之一:
 Restangular.all('advertiser').one("?id=" + 1).getList().then(function(data) {
   $scope.advertiserName = data.name;
   $scope.advertiserId = data.id;
 });

 $scope.title = $scope.advertiserName;
 $scope.id = $scope.advertiserId;

在作用域上初始化正确的属性:

 Restangular.all('advertiser').one("?id=" + 1).getList().then(function(data) {
     $scope.title = data.name;
     $scope.id = data.id;
 });

将其改为引用更新:
 var advertiser = {
     id: $scope.advertiser,
     title: $scope.advertiser
 }
 $scope.advertiser = advertiser;

 Restangular.all('advertiser').one("?id=" + 1).getList().then(function(data) {
     advertiser.title = data.name;
     advertiser.id = data.id;
 });

由于使用 Angular 的 Promise 已经触发了脏检查循环,因此视图将会被更新。


1
如果我理解正确,这是由于异步调用的原因。异步意味着发送请求(或者更确切地说是接收响应)被取出了正常的执行流程。在你的例子中,$.ajax立即返回,而下一条语句return result;在传递给成功回调函数的函数甚至被调用之前就执行了。你应该像这样做:
$scope.someFunction = function () {
 Restangular.all('advertiser').one("?id=" + 1).getList().then(function(data) {
   return $scope.advertiserName = data.name;
 });
}
$scope.title = $scope.someFunction(); //It will give you output

编辑1:

我阅读了许多相关的文章,发现异步调用的响应将从正常的执行流中取出。无论您使用restangule还是$http调用,都是异步调用。因此,编译器不会等待您的响应。您需要告诉编译器等待ajax响应。在我的一个项目中,我做了什么。这里有一个简单的例子可以更好地说明。

首先,我声明了一个控制器函数。如下所示

$scope.asynchronousCallee = function (){
 $http.get('/url').
  success(function(data, status, headers, config) {
    $scope.myAjaData = data;
  });
}

$scope.asynchronousCallee(); //Call above function just after the declaration

这个函数将通过get调用从服务器接收数据,并将响应分配给变量,但请注意,此成功函数将被异步调用。因此,我在声明它之后立即调用了asynchronousCallee函数。现在编译器将等待此函数的响应,并在执行该函数后继续执行。希望这可以帮助你,兄弟 :-)


我实际上正在寻找您所说的同步调用。谢谢Vineet。但是在$scope.someFunction完成之前,$scope.title就已经被执行了。我还想在$scope.someFunction执行后执行紧接着$scope.title的代码。 - Inaccessible
@Inaccessible,请看一下我的修改后的答案。它对我非常有效,希望对你也有用 :-) - Vineet

0
 Restangular.all('advertiser').one("?id=" + 1).getList().then(function(data) {
   $scope.advertiserName = data.name;
   $scope.advertiserId = data.id;
    return { name : data.name, id : data.id };
 }, function(er){
    //Handle error
 })
.then(function(response){
  $scope.title = response.name;
  $scope.id = response.id;
}, function(er){
  //Handle error
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接