11
\$\begingroup\$

I am trying to build a food search app. I am using Angular and Spring. I am currently using the yelp API, but it's done on the Java side.

I think what I have achieved is really bad design. It works, but the data is not always updated correctly.

For Java, I created two methods and one string variable:

private String response;

@RequestMapping(value = "/searchRestaurant", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public void searchRestaurantWithYelp(@RequestBody String jsonData) {

    //here i process the json string and pass the values to yelp function,
    // then yelp sends the respond as a json string, i assigned the value
    // to the response variable.
    response = queryYelp();
}

As you can see, this post request receive a json string from client side, and pass the string to the yelp java API I created. The yelp respond is a json string, and I assign it to the response variable.

I also created a GET method, which simply returns the response, which contains the data yelp returned. I want to immediately return this data to the client/browser, with angular.

@RequestMapping(value = "restaurantResult", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public String returnRestaurantSearchResultWithYelp() {
    return response;
}

Now for my JS/angular side of code:

function HomeCtrl($scope, $http) {
    $scope.term = "";
    $scope.location = "";
    $scope.submitSearch = function () {
        var data = {
            term: $scope.term,
            location: $scope.location
        }; //end data
        var res = $http.post('/searchRestaurant', data);
        $http.get('/restaurantResult').
              success(function (data) {
        $scope.response = data;
        });
    }
 } 

I wrapped a $http.get inside the $http.post. This function first sends data, which invoke my Java post method, then retrieves the data right after. I am binding the json data with angular so my app is single page. And with angular two way data binding the {{response}} contains the yelp response and will display instantly to the user.

My simplified HTML:

 <input type="text" ng-model="term"/>
 <input type="text" ng-model="location"/>
 <button ng-click="submitSearch()">Search</button>

 {{response}}

It works, sort of. But I feel there is a better way to do it.

The issue: The {{response}} sometimes cannot be updated instantly. For instance, I search burger king, the response will show me the address, location, etc. Then I type McDonalds, the response still shows the info of Burger King. I have to refresh the browser to get the latest and correct response.

I was wondering what the issue is causing the response not update instantly? Is it because of browser cache?

In terms of the my project build design, what part I did wrong? Is there a better way to handle this type of request?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

I type McDonalds, the response still shows the info of Burger King. I have to refresh the browser to get the latest and correct response.

The request is being made before the previous post completes.

In your Angular, you need to chain your $http actions

function HomeCtrl($scope, $http) {
    $scope.term = "";
    $scope.location = "";
    $scope.submitSearch = function () {
        var data = {
            term: $scope.term,
            location: $scope.location
        }; //end data
        var res = $http.post('/searchRestaurant', data);

        //chain from the post
        res.then ( function() { 
            return $http.get('/restaurantResult').
        }).then ( function(result) {
            $scope.response = result.data;
            return data;
        }).catch ( function(error) {
            //log error
            throw error;
        });

        //return for further chaining
        return res;
    }
 } 

By chaining your actions, you guarantee that the previous action completes before starting the next.

Notice that the .then method returns data differently than the .success method.

Also I avoid the .success and .error methods for two reasons: They ignore return values and they are deprecated. For more information on tbe deprecation of .success and .error, see the AngularJS $http Service API Reference -- deprecation notice.

For more information on chaining see AngularJS $q Service API Reference - chaining promises.

UPDATE

To answer you questions about the differences between .then and .catch methods and the deprecated .success and .error methods.

The $http service .then method returns a response object to its resolve callback.

// Simple GET request example:
$http({
  method: 'GET',
  url: '/someUrl'
}).then(function resolveCallback(response) {
    // this callback will be called asynchronously
    // when the response is available
  }, function catchCallback(response) {
    // called asynchronously if an error occurs
    // or server returns response with an error status.
  });

The response object has these properties:

  • data – {string|Object} – The response body transformed with the transform functions.
  • status – {number} – HTTP status code of the response.
  • headers – {function([headerName])} – Header getter function.
  • config – {Object} – The configuration object that was used to generate the request.
  • statusText – {string} – HTTP status text of the response.

--- AngularJS $http Service API Reference -- general usage

Deprecated: The $http service .success method spreads out the response object.

// Simple GET request example :
$http.get('/someUrl').
  success(function(data, status, headers, config) {
    // this callback will be called asynchronously
    // when the response is available
  }).
  error(function(data, status, headers, config) {
    // called asynchronously if an error occurs
    // or server returns response with an error status.
  });

As I said before, avoid these method for two reasons: they ignore return values and they are deprecated.

The rule of thumb for functional programming is always return something. By ignoring return values, .success and .error break that rule. What makes promises powerful is returning and chaining.

\$\endgroup\$
4
  • \$\begingroup\$ Welcome to Code Review! Good job on your first answer. \$\endgroup\$
    – SirPython
    Dec 19, 2015 at 22:19
  • \$\begingroup\$ How exactly .then returns different data than .success? \$\endgroup\$
    – OPK
    Dec 21, 2015 at 14:02
  • \$\begingroup\$ @JasonZ see updated answer. \$\endgroup\$
    – georgeawg
    Dec 21, 2015 at 14:48
  • \$\begingroup\$ @georgeawg great. thanks for the detailed answer. \$\endgroup\$
    – OPK
    Dec 21, 2015 at 15:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.