How does asynchronous call work in AngularJS 1.X?

2020-05-06 04:55发布

I have the following function named getvalue. It is inside an AngularJS module together with a controller. I am trying to call this function on click event invoking another function in a controller.(I hope I am clear)

function:

  function getvalue(Data, $http) {
            var value=undefined;
           $http({
                url: /myurl,
                method: "GET",
                params: {
                    tmp: Data.tmp,
                    pressure: Data.pressure               
                }
            }).success(function (data, status, headers, config) {            
                value=parseFloat(  console.log(data));//console working here
               return value;
            });
        return value;
        }

Code inside Controller

 value= getvalue(formData, $http );
        alert(value);//undefined here. Seems like value is never changed.

I have not getting the value on alert but console is printing the value. I need help if possible for two issues.

  1. How can I change the value from inside success and return to controller?
  2. Is there any way that I don't have to inject $Http from controller to function? -----It would be nice if I can do that for unit testing.

4条回答
我命由我不由天
2楼-- · 2020-05-06 05:35

A $http-Request is async. That means that alert will be called before the .success(..) callback is executed.

You can see a result on the console because it reflects changes made after the call of console.log().

Calling alert(value); in the .success()-Callback will shield the desired result.

查看更多
戒情不戒烟
3楼-- · 2020-05-06 05:42

Replace:

 }).success(function (data, status, headers, config) {            
     value=parseFloat(  console.log(data));//console working here
     return value;
});

with:

 }).success(function (data, status, headers, config) {            
     alert(parseFloat(data));
});
查看更多
劳资没心,怎么记你
4楼-- · 2020-05-06 05:49

you would ideally want to pull the $http service out of the controller and make a factory to do those calls.

in the factory have a function that accepts the data you are wanting to send and have it return the promise back to the controller

something like this

Repo

app.factory("fooRepo", ["$http", function($http){
    return {
        getValue: function(data){
            return $http({
                method: "POST",
                url: "/myUrl"
            });
        }
    };
}]);

Serivce

app.factory("foo", ["$q", "fooRepo", function($q, fooRepo){
    return {
        getValue: function(data){
            var deferred = $q.defer();

            fooRepo.getValue(data)
            .success(function(results){
                //do some work
                deferred.resolve(results);
            })
            .error(function(error){
                // do some work
                deferred.reject(error);
            });

            return deferred.promise;
        }
    }
}]);

here is the controller

app.controller("fooCtrl", ["foo", function(foo){
    foo.getValue(dataHere)
        .then(function(results){
            // do something here
        });
}]);

Added Plunkr

查看更多
【Aperson】
5楼-- · 2020-05-06 05:57

As you are calling a method which is doing async call, you must return promise from there as you don't know when data will get back from the ajax. On success of that ajax you should update your variable. Outside of ajax function you will get undefined value because value is returned in async manner.

Function

 function getvalue(Data) {
      var value=undefined;
      return $http({
          url: /myurl,
          method: "GET",
          params: {
              tmp: Data.tmp,
              pressure: Data.pressure               
            }
      })
}

Controller

 getvalue(formData).success(function (data, status, headers, config) {            
      console.log(data);//you will get data here
 });
查看更多
登录 后发表回答