AngularJS - Best Practices for Handling Multiple API Requests

Greetings, I am new to Angular and seeking guidance on optimizing the following code snippet. While it does function as intended, I believe there must be a more efficient approach. I've delved into various resources and it seems structuring these tasks within factories could be beneficial. However, my attempts thus far have resulted in errors, likely due to my own oversight.

Essential Requirements

  • I require compatibility within a module (to incorporate custom directives)
  • The functionality involves 3 API calls: 2 via GET method, while one necessitates POST method usage

Snippet Overview:

$apiUrl = '_includes/gtmetrix.php'; // Utilizing a local proxy for remote API access.
$apiKey = '';
$gapiUrl = 'https://www.googleapis.com/pagespeedonline/v1/runPagespeed';
$gapiKey = '1z2x3c4v5b6n7m8a9s';
$gapiStrategy = 'mobile';
$requestUrl = '<?php echo $_POST['url']; ?>';

function FetchCtrl($scope, $http, $templateCache) {

    $scope.method = 'POST';
    $scope.url = $requestUrl;

    $scope.fetch = function() {
        $scope.code = null;
        $scope.response = null;

        $http({method: $scope.method, url: $apiUrl + '?url=' + $scope.url, cache: $templateCache}).
        success(function(data, status) {
            $scope.status = status;
            $scope.data = data || "Request successful";
        }).
        error(function(data, status) {
            $scope.data = data || "Request failed";
            $scope.status = status;
        });
    };
    $scope.fetch();

    $scope.fetchGoogle = function() {
        $scope.code = null;
        $scope.response = null;

        $http({method: 'GET', url: $gapiUrl + '?url=' + $scope.url + '&key=' + $gapiKey, cache: $templateCache}).
        success(function(data, status) {
            $scope.status = status;
            $scope.datag = data || "Request successful";
        }).
        error(function(data, status) {
            $scope.datag = data || "Request failed";
            $scope.status = status;
        });
    };
    $scope.fetchGoogle();

    $scope.fetchGoogleMobile = function() {
        $scope.code = null;
        $scope.response = null;
        // $scope.data = '<i class="fa fa-spinner fa-spin"></i>';

        $http({method: 'GET', url: $gapiUrl + '?url=' + $scope.url + '&key=' + $gapiKey + '&strategy=' + $gapiStrategy, cache: $templateCache}).
        success(function(data, status) {
            $scope.status = status;
            $scope.datagm = data || "Request successful";
        }).
        error(function(data, status) {
            $scope.datagm = data || "Request failed";
            $scope.status = status;
        });
    };
    $scope.fetchGoogleMobile();

    $scope.updateModel = function(method, url) {
        $scope.method = method;
        $scope.url = url;
    };

}

I have been grappling with this setup for quite some time now, so any assistance or pointers would be highly valued. Thank you!

Answer №1

If you're looking for a solution, consider utilizing the convenient $http.get() and $http.post() methods. Another option is to explore using $resource, as suggested by Klaster_1. It seems like there might be some redundant code in your current implementation. Starting with a basic setup like this and gradually expanding it may be a good approach.

function DataRetrievalCtrl($scope, $http) {
    var googleApiBaseUrl = "https://www.googleapis.com/pagespeedonline/v1/runPagespeed?url=<?php echo $_POST['url']; ?>&key=1z2x3c4v5b6n7m8a9s";

    $http.post("_includes/gtmetrix.php?url=<?php echo $_POST['url']; ?>")
        .success(function(data) {
            $scope.data = data;
        });

    $http.get(googleApiBaseUrl)
        .success(function(data) {
            $scope.datag = data;
        });

    $http.get(googleApiBaseUrl + "&strategy=mobile")
        .success(function(data) {
            $scope.datagm = data;
        });
}

Answer №2

Here's my method. I prefer using $resource over $http. It should help you get started, and you might find the built-in functions of $resource useful.

My Approach:

.factory('WorkOrder', function($resource){

// Utilizing $resource: $resource(url[, paramDefaults][, actions]);
return $resource('/controller/get/:id.json', {}, {
    /*
     * The default actions are as follows; feel free to modify or add more
     * { 'get':    {method:'GET'},
     *   'save':   {method:'POST'},
     *   'query':  {method:'GET', isArray:true},
     *   'delete': {method:'DELETE'} };
     */
});

})

My Controller:

// Retrieve work order data based on the ID from the tag attribute
var getWO = function() {

WorkOrder.get({woId:$attrs.id},

    // Success callback
    function(response) {
        // Assigning work order data to the scope
        $scope.WorkOrder            = response.WorkOrder;
    },

    // Failure callback
    function(response) {
        // Handle failure...
    }
);
};
getWO();

I place my success and failure functions in the controller because that's where I know best how to handle responses. I also save the function to a variable and call it immediately after in case I need to use it within a $timeout or elsewhere.

You can create multiple factory functions as needed. If there's a dependency between them, consider placing the dependent call inside the success callback of your controller.

Hopefully, this addresses your query.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The style properties of Material UI ButtonGroup are not being properly applied

https://i.sstatic.net/apxUH.gif Within a Grid container, I have a Product image with associated buttons. The visibility of these buttons is determined by specific state variables. If the product quantity is 0, an "ADD TO CART" button is displayed; otherwi ...

Creating a dynamic dashboard filled with widgets - each time a new widget is added, the postback triggers a reload of all the current widgets

After my initial attempt at building a dashboard in a webforms project, I have successfully implemented the following features: Users can add/remove/move widgets However, a significant issue has arisen: Whenever a new widget is added, all other widgets ...

Authentication using SPA RSA 2048 encryption technology

For my current project involving Angular SPA development, the customer has requested the use of RSA 2048 for authentication. I'm uncertain about how the authentication token will be generated. My understanding is that the token should be created on th ...

An HTML attribute with a blank value will not display the equals sign operator

jQuery can be used like this: $select.append('<option value="">All</option>'); This code appears to insert the element in HTML as follows: <option value>All</option> However, what is intended is to append the elemen ...

React Native error: Attempting to convert an undefined value to an object

I'm trying to fetch data like this: useEffect(() => { async function getData() { const response = await fetch('https://hasanadiguzel.com.tr/api/kurgetir'); const json = await response.json(); setData(json ...

Function cannot be called upon directive initialization

I'm currently developing a custom directive in AngularJS and I am facing an issue with calling a function upon loading my directive. My attempt to call the function within the link function resulted in an error message saying TypeError: scope.setCurr ...

Combine various values from object properties into a single string

If there is an object structured like this: let example = { key1: "data1", key2: "data2", key3: "data3", key4: "data4", key5: "data5" } Given that the keys are fixed but not always in a specific order, what would be the most effi ...

Safari browser cutting off POST parameters prematurely

I am encountering an issue where my code works perfectly on all browsers except Safari 6.1.2 on Mac OS Lion. Below is the AJAX post code that I am using - $.ajax({ type: 'POST', dataType: 'text/html', url:"/MyProxy.php ...

Error: Insufficient values to unpack when executing unit tests for a Django ModelViewSet

My current challenge involves testing an endpoint that retrieves data using a ModelViewSet. I am passing a parameter via a URL to this endpoint in order to retrieve the data. However, when running the unit tests, I encounter the following error: File &q ...

Why is the response from this HTTP request displaying array lengths instead of actual content?

I am currently working on a project involving fetching data asynchronously from an API. Everything seems to be working fine, except for when I attempt to add the correct answer to the incorrect answers array. Instead of displaying the content, only the len ...

What is the best way to make a recursive function display every return value in Javascript?

I need help with a function I have been working on. function main() { //retrieve the start text var start_text = document.getElementById("start_text").value; //retrieve target text var target_text = document.getElementById("target_text"). ...

Ajax dropdown menu displaying 'Loading Data' message during processing

Is it possible to display a Please wait.. or Loading... label underneath my Combo box while data is loading? I would like to show a Loading... message under the switch box when switching between Male and Female. https://i.sstatic.net/zpFDF.jpg This is th ...

Save the JWT token securely within a closure

Someone mentioned that the recommended way to store JWT tokens is as follows: access_token in the application memory (like closures) refresh_token in cookie entries (HttpOnly) Currently, my access_token is stored in localStorage and used for checking aut ...

I'm looking to transform this array into the format described below, and also include another nested subarray within it using TypeScript

[{ "header": "API", "value": "hello" }, { "header":"API", "value":"yellow" }, { "header":"Other", "value":"yallow"}, { "header":"other", "value":"othertt" } ] I have a list of objects with he ...

Commands for banning or kicking users in discord.js

Basically, I am looking for simple commands that allow me to type: <ban [user here] or <kick [user here] and have it kick/ban the referenced user. I understand this may seem basic, but I am new to Discord bot coding and JavaScript in general. Can a ...

When using node.js, the initial request yields no response while the subsequent request provides the expected data

Currently, I am in the process of setting up a node.js API using Express, Body-parser, and MySQL. An issue I am encountering is that when making a GET request to a route for the first time, it returns blank. However, on the second attempt, it retrieves th ...

Accordion feature exclusively toggles the initial item

I am having an issue with the code in my index.php file. Only the first item in the accordion menu is showing up correctly. When I click on "Status" or "Repeated", I expect to see the sub-menu of the clicked item, but instead, I am getting the result from ...

Strange outcome received from THREE.JS - Vector3.project function

Currently I am working on a project in THREE.JS and I am encountering an issue with projecting a Vector3. When attempting to project the Vector3 (0,0,0), which should ideally appear at the center of my camera screen, I receive NaN as the result. Surprising ...

Looking to conduct date comparisons within angular-ui-grid?

I'm currently working on an application that utilizes angular-ui-grid to display form data. One issue I'm facing is how to compare the submission date obtained from an API call with the current date within ui-grid, in order to calculate the numbe ...

The page does not seem to be reloading properly due to a redirect issue

I am currently updating some data and then attempting to reload the current page. After discovering the status code that allows me to switch the redirect method from put to get (303), I noticed that it is functioning correctly. However, despite seeing "fi ...