Javascript AngularJS与摘要/应用的异步特性

Javascript AngularJS与摘要/应用的异步特性,javascript,php,angularjs,asynchronous,Javascript,Php,Angularjs,Asynchronous,我经常遇到一个问题,在父控制器中设置了一个范围变量,而子控制器调用这个范围变量。但是,它在函数能够设置scope元素之前调用它,导致它返回undefined。例如: 父控制器: module.controller('parent', '$scope', '$http', function ($scope, $http) { $scope.init = function(profileID, profileViewStatus) { //Initiiaze user properities

我经常遇到一个问题,在父控制器中设置了一个范围变量,而子控制器调用这个范围变量。但是,它在函数能够设置scope元素之前调用它,导致它返回undefined。例如:

父控制器:

module.controller('parent', '$scope', '$http', function ($scope, $http) {
$scope.init = function(profileID, profileViewStatus) {
    //Initiiaze user properities
    $http.get(requestUserInformationGetURL + profileID)
        .success(function(profile) {
            $scope.profile = profile;
            $scope.userID = profile.user_id;
            $scope.username = profile.username; 
            console.log($scope.userID);
        })
        .error(function() {
            exit();
        });
}
module.controller('child', function($scope, $http, fetchInfo) {

console.log($scope.userID);

//Fetch the HTTP POST data for the user profile
var promise = $http({
    method: "post",
    url: fetchInfo,
    data: {
        user_id: $scope.userID //From the parent controller
    },
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
promise.then(function(successResponse) {
    //Populate the scope, log the data
    console.log(successResponse);
    $scope.data = successResponse.data;
}, function(error) {
    alert(error);
});
$scope.init().then(function(userID){
    var promise = $http({
    method: "post",
    url: fetchInfo,
    data: {
        user_id: userID //From the parent controller
    },
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
   });
   promise.then(function(successResponse) {
    //Populate the scope, log the data
    console.log(successResponse);
    $scope.data = successResponse.data;
   }, function(error) {
    alert(error);
  });
})
.catch(function(error){
 console.log('error');
})
子控制器:

module.controller('parent', '$scope', '$http', function ($scope, $http) {
$scope.init = function(profileID, profileViewStatus) {
    //Initiiaze user properities
    $http.get(requestUserInformationGetURL + profileID)
        .success(function(profile) {
            $scope.profile = profile;
            $scope.userID = profile.user_id;
            $scope.username = profile.username; 
            console.log($scope.userID);
        })
        .error(function() {
            exit();
        });
}
module.controller('child', function($scope, $http, fetchInfo) {

console.log($scope.userID);

//Fetch the HTTP POST data for the user profile
var promise = $http({
    method: "post",
    url: fetchInfo,
    data: {
        user_id: $scope.userID //From the parent controller
    },
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
promise.then(function(successResponse) {
    //Populate the scope, log the data
    console.log(successResponse);
    $scope.data = successResponse.data;
}, function(error) {
    alert(error);
});
$scope.init().then(function(userID){
    var promise = $http({
    method: "post",
    url: fetchInfo,
    data: {
        user_id: userID //From the parent controller
    },
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
   });
   promise.then(function(successResponse) {
    //Populate the scope, log the data
    console.log(successResponse);
    $scope.data = successResponse.data;
   }, function(error) {
    alert(error);
  });
})
.catch(function(error){
 console.log('error');
})
HTML:


但它不起作用,我认为它的语法不正确。我想,我不完全理解AngularJS的Asycn本质,这种情况发生过多次。如何控制DOM加载元素来解决类似问题?

在这种情况下,正确的方法是使用专用服务来处理异步操作、请求、数据缓存等。但由于您还没有服务层,我将使用控制器范围Promise对象提出简单的基于Promise的解决方案

检查您修改的代码:

module.controller('parent', ['$scope', '$http', function ($scope, $http) {
    $scope.init = function (profileID, profileViewStatus) {
        $scope.profilePromise = $http.get(requestUserInformationGetURL + profileID).success(function (profile) {
            $scope.profile = profile;
            $scope.userID = profile.user_id;
            $scope.username = profile.username;
        })
        .error(exit);
    }
}]);

module.controller('child', function($scope, $http, fetchInfo) {

    // Fetch the HTTP POST data for the user profile
    $scope.profilePromise.then(function() {
        return $http({
            method: "post",
            url: fetchInfo,
            data: { user_id: $scope.userID },
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
        });
    })
    .then(function(successResponse) {
        console.log(successResponse);
        $scope.data = successResponse.data;
    }, function(error) {
        alert(error);
    });
});
正如您所看到的,仍然调用父控制器
init
方法,但现在它立即设置范围属性
profilePromise
,该属性可在子控制器中访问


子控制器使用父控制器的
然后
方法
profilePromise
对象,它保证使用
$scope.userID
请求
$http
将在配置文件已经可用后触发。

通常,您会使用UI路由器的路由解析来确保在构建任何一个控制器之前完成工作。子状态会自动访问其父状态的解析

 //Router configuration
.state('app.inspections.list', {
    url: '',
    templateUrl: 'Template/parent',
    controller: "Parent as vm",
    resolve: {
        profile: ['$http', function ($http) {
            return $http.get(requestUserInformationGetURL + profileID)
                .success(function(profile) {                    
                    console.log(profile.userID);
                    return profile;
                })
                .error(function() {
                    exit();
                });
        }]
    }
}).state('parent.child', {
    url: 'child',
    templateUrl: 'Template/child',
    controller: "Child as vm"
})

   //parent controller
    module.controller('parent', '$scope', 'profile', function ($scope, profile){
        $scope.profile = profile;
        $scope.userID = profile.user_id;
        $scope.username = profile.username; 
    }

//child controller
module.controller('child', 'profile', function($scope, $http, fetchInfo, profile){

console.log(profile.userID);

//Fetch the HTTP POST data for the user profile
var promise = $http({
    method: "post",
    url: fetchInfo,
    data: {
        user_id: profile.userID //From the parent controller
    },
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
promise.then(function(successResponse) {
    //Populate the scope, log the data
    console.log(successResponse);
    $scope.data = successResponse.data;
}, function(error) {
    alert(error);
});
您可以使用promise($q服务):尝试使用以下代码:

父控制器:

$scope.init = function(profileID, profileViewStatus) {
    var deferred = $q.defer();
    $http.get(requestUserInformationGetURL + profileID)
        .success(function(profile) {
            $scope.profile = profile;
            $scope.userID = profile.user_id;
            $scope.username = profile.username; 
            deferred.resolve($scope.userID);
            console.log($scope.userID);
        })
        .error(function() {
            deferred.reject('error');
            exit();
        });
       return deferred.promise;
}
不要在父控件中调用init方法

在子控制器中:

module.controller('parent', '$scope', '$http', function ($scope, $http) {
$scope.init = function(profileID, profileViewStatus) {
    //Initiiaze user properities
    $http.get(requestUserInformationGetURL + profileID)
        .success(function(profile) {
            $scope.profile = profile;
            $scope.userID = profile.user_id;
            $scope.username = profile.username; 
            console.log($scope.userID);
        })
        .error(function() {
            exit();
        });
}
module.controller('child', function($scope, $http, fetchInfo) {

console.log($scope.userID);

//Fetch the HTTP POST data for the user profile
var promise = $http({
    method: "post",
    url: fetchInfo,
    data: {
        user_id: $scope.userID //From the parent controller
    },
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
promise.then(function(successResponse) {
    //Populate the scope, log the data
    console.log(successResponse);
    $scope.data = successResponse.data;
}, function(error) {
    alert(error);
});
$scope.init().then(function(userID){
    var promise = $http({
    method: "post",
    url: fetchInfo,
    data: {
        user_id: userID //From the parent controller
    },
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
   });
   promise.then(function(successResponse) {
    //Populate the scope, log the data
    console.log(successResponse);
    $scope.data = successResponse.data;
   }, function(error) {
    alert(error);
  });
})
.catch(function(error){
 console.log('error');
})

您的问题可能是正在异步调用
$.get
,这是默认行为。您的
init
方法实际上可能会按照您期望的顺序被调用,但实际发生的情况是:

  • 调用父
    init
  • 调用了
    $.get
    ,但服务器的响应不是即时的
  • 调用子
    init
  • 获取从服务器返回的数据
  • $.get(..).success(函数(数据){…})来处理数据
我会建议其他人是什么,用承诺来推迟执行