-->

How to pass data from one asynchronous to another

2019-08-20 02:19发布

问题:

How to pass global variable value from one function to another function in angular?

I have 2 global variables as:

$scope.genewtId = null;
$scope.data1 = null;

I have 2 angular functions which look as below:

$scope.getID = function() {
    Service1.getId("abc").then(function(response){
        $scope.genewtId = response.data[0].Id;
        console.log($scope.genewtId);

    }, function(error){
        console.log(error.statusText);
    });
};

$scope.getDetails = function() {
    Service2.getDetails($scope.genewtId).then(function(response){
        // here response is having an error
        $scope.data1 = response.data;
        console.log($scope.data1.toString());
    }, function(error){
        console.log(error.statusText);
    });
};

When I pass value of $scope.genewtId from one function to another function, I get an error

message: "Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer'; nested exception is java.lang.NumberFormatException: For input string: "null""

However, console.log($scope.genewtId); is returning a value 787651 which means it is not null.

Please suggest if it can be implemented using $rootScope.$broadcast

回答1:

The promises from the two services need to be chained

Modify the first function to return a promise:

$scope.getID = function() {
    return Service1.getId("abc").then(function(response){
        $scope.genewtId = response.data[0].Id;
        console.log($scope.genewtId);
        return response.data[0].Id;
    }, function(error){
        console.log(error.statusText);
        throw error;
    });
};

Modify the second function to both return a promise and accept an argument:

$scope.getDetails = function(id) {
    var genewtID = id || $scope.genewtId;
    return Service2.getDetails(genewtId).then(function(response){
        $scope.data1 = response.data;
        console.log($scope.data1.toString());
        return response.data;
    }, function(error){
        console.log(error.statusText);
        throw error;
    });
};

Then chain the two promises:

var promise = $scope.getId();

var promise2 = promise.then(function(id) {
                   return $scope.getDetails(id);
               });

var promise2.then(function(data) {
     console.log(data);
}).catch(function(error) {
     console.log(error);
});

By using the .then method of the getId promise, the code waits for the id value to arrive from the server before making the request to getDetails.

Because calling the .then method of a promise returns a new derived promise, it is easily possible to create a chain of promises. It is possible to create chains of any length and since a promise can be resolved with another promise (which will defer its resolution further), it is possible to pause/defer resolution of the promises at any point in the chain.

For more information, see

  • AngularJS $q Service API Reference - Chaining Promises
  • You're Missing the Point of Promises


回答2:

The only reason I can think of is because of asynchronous call of promises. What's happening is that :

Somehow, you are calling Service2.getDetails($scope.genewtId) before the value of $scope.genewtId has been set after the promise completion of Service1.getId("abc").then, and so the value remains null

Try:

$scope.getID = function(isCalledAfterDetails) {
    Service1.getId("abc").then(function(response){
        $scope.genewtId = response.data[0].Id;
        console.log($scope.genewtId);
        if(isCalledAfterDetails && $scope.genewtId !== null){
            $scope.getDetails();
        }

    }, function(error){
        console.log(error.statusText);
    });
};

$scope.getDetails = function() {
    if($scope.genewtId === null){
        $scope.getID(true);
    }else{
        Service2.getDetails($scope.genewtId).then(function(response){
            // here response is having an error
            $scope.data1 = response.data;
            console.log($scope.data1.toString());
        }, function(error){
            console.log(error.statusText);
        });
    }

};

Even, if this approach works, I would strongly suggest you to implement the function calls in a better way because $scope.getDetails() is dependent on $scope.getID() for setting value of $scope.genewtId.

If you want suggestion on how to implement it, please update the question with the use case and some more code

Update

$scope.getID = function() {
    Service1.getId("abc").then(function(response){
        $scope.genewtId = response.data[0].Id;
        $scope.getDetails();
    }, function(error){
        console.log(error);
    });
};

$scope.getDetails = function() {
        Service2.getDetails($scope.genewtId).then(function(response){
            // here response is having an error
            $scope.data1 = response.data;
            console.log($scope.data1.toString());
        }, function(error){
            console.log(error.statusText);
        });        
};

Using service

In service.js

getDetails = function(id){
    var deferred = $q.derfer();
    $http.get('/user/'+id).then(function(response){
        var newId = response.data[0].Id;
        $http.get('/user/details'+newId).then(function(details){
            deferred.resolve(details)
        })
    })      
    return deferred.promise;
}

controller.js

$scope.getDetails = function() {
        MySvc.getDetails("abc").then(function(response){
            console.log(response) // your details here
        }, function(error){
            console.log(error.statusText);
        });        
};


回答3:

It seems like the exception is coming from the server side.

Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer'; nested exception is java.lang.NumberFormatException: For input string: "null"

It is getting printed on the console due to console.log(error.statusText);

You need to verify the logic when the value is used in the API.