Asynchronous image uploads with jQuery on a website

- Andrés Cruz

En español
Asynchronous image uploads with jQuery on a website

AJAX, for its acronym in English, Asynchronous JavaScript And XML, is nothing more than a technology that allows you to create applications that maintain asynchronous communication with the server; In other words we can execute functions in parallel with JavaScript using AJAXs with jQuery; which turns out to be a simple but at the same time powerful way due to the large number of possibilities it offers and how easy it is to integrate it with other sections of code (since in the end it is JavaScript).

One of the big problems that the current approach has when creating web pages is that every time we add dependencies through JavaScript or CSS and even other resources such as images and videos, all of these things when consulted through a web page, The browser gradually processes the content of the website from the beginning to the end. When it reaches the loading of a CSS or JavaScript file, the browser stops loading the HTML until it finishes loading the CSS or JavaScript resource in question. then continue with the rest of the load; Surely on more than one occasion when you include jQuery on your website and try to use some functionality of this JavaScript framework, the browser in your console gives an error something like:

Uncaught TypeError: Cannot read property 'XXX' of undefined at <anonymous> </anonymous>

And it is due to the above explained, if you place any code that depends on an external library, this will not work (and will give an error) until the corresponding resource is loaded.

The problem of asynchronous loading in JavaScript

The problem of asynchronous loading in JavaScript

What does AJAX offer us?

With the above, Ajax or asynchronous loads through JavaScript or our case of interest for this entry, jQuery, which offers a simpler way of asynchronous loads than pure JavaScript, comes into play.

Before getting into the topic, let's remember that a long time ago the people at Microsoft invented a technology that would later be known as AJAX, which was quite primitive and in the end only allowed the use of one thread in our app (the main thread of the UI), made the request and blocked the rest of the app until it finished executing, which has evolved quite a bit to date.

Now returning to our case of interest, which is to develop applications that run in parallel; AJAX we can do a multitude of things to create interactive pages without the need to refresh all the elements of the page:

  • We can obtain data in JSON or XML format, although the former has been gaining relevance with respect to the latter.
  • We can obtain a complete page (HTML, CSS, JavaScript) and manipulate it as we wish from JavaScript.
  • We can receive information asynchronously or synchronously depending on our needs.

But... what can we use AJAX for?

  • Imagine that you want to put together two lists, one of companies, and another of suppliers where a supplier belongs to a company; without going too far into what the data model would be like; The user must select a company to be able to load a list of suppliers that belong to the company. This loading can be done through AJAX asynchronously without reloading the entire document; we just get the list of suppliers and fill it inside the list.
  • Imagine that you want to show an overlay of different pages from the main page according to some option selected by the user; This loading of web pages or sections can be done in a very simple way with AJAX.

With AJAX none of the above actions require a full page load (as they would if you didn't use AJAX), simply refreshing sections of the document; We can even load less necessary resources asynchronously such as images:

jQuery.ajax() Parameters

jQuery.ajax() handles a large number of parameters that allow AJAX to be configured in many ways according to our needs; but among those that I consider most important we can mention the following:

URL of the resource to which you want to send the request.
async (default: true): By default all requests are configured to be asynchronous; which means that the rest of the JavaScript continues to execute regardless of whether I finish processing the request.
contentType: Explicitly indicates the type of data to receive from the server.
error: Function that is invoked when an error occurs with the request, including errors and/or server status: 500, 404, 400, etc.
success: Function that is invoked when the request was successfully processed.
type: GET or POST as the case may be.

Examples with AJAX and jQuery

In this section we will see a set of examples to demonstrate some of the functionalities of AJAX and exemplifying its use along the way; throughout the examples we reference some files through their URL:

The page.html file contains: <html> <head> <title>My page</title> </head> <body> <h3>My page</h3> </body> </html>
The test.php file redirects to page.html: <?php readfile('page.html');
The test2.php file returns a JSON:

<?php
if(isset($_GET['id']))
 echo '{
    "aaData": [
        {
            "id": "132",
            "nombre_autor": "Jean",
            "apellido_autor": "Arp",
            "nombre_tipo": "Escultura",
            "nombre_zona": "Plaza Cubierta del Rectorado"
        },
        {
            "id": "133",
            "nombre_autor": "Jean",
            "apellido_autor": "Arp",
            "nombre_tipo": "Elementos plásticos",
            "nombre_zona": "Edif. de la Facultad de Humanidades y Educación"
        }
    ]
}';

Example of a simple jQuery.ajax()

The simplest AJAX that I consider we can create with jQuery should be something very similar to the following script:

var url="test.php";

$.ajax({
type : "GET",
url : url,
success : function(data) {
console.log("data",data);
},
error : function(objXMLHttpRequest) {
console.log("error",objXMLHttpRequest);
}
});

Or we can even obtain the page directly:

var url="pagina.html";

$.ajax({
type : "GET",
url : url,
success : function(data) {
console.log("data",data);
},
error : function(objXMLHttpRequest) {
console.log("error",objXMLHttpRequest);
}
});

In both cases, if we look at the developer console, we would see something like this:

data <html>
<head>
<title>Mi página</title>
</head>
<body>
<h3>Mi página</h3>
</body>
</html>

We got the content of the HTML page called page.html using AJAX.

We did?

We only send a request to the resource indicated in the url parameter and it returns content.

The resource could also be an XML, JSON, a file, etc.

jQuery.ajax() example with parameter passing

If our resource needs to pass one or more parameters, it is necessary to use the data parameter as we will see below:

var url="test2.php";
$.ajax({
type : "GET",
data : {
	id : 5
},
url : url,
success : function(data) {
console.log("data",data);
},
error : function(objXMLHttpRequest) {
console.log("error",objXMLHttpRequest);
}
});

If we look at the developer console, we would see a String like this:

data {
    "aaData": [
        {
            "id": "132",
            "nombre_autor": "Jean",
            "apellido_autor": "Arp",
            "nombre_tipo": "Escultura",
            "nombre_zona": "Plaza Cubierta del Rectorado"
        },
        {
            "id": "133",
            "nombre_autor": "Jean",
            "apellido_autor": "Arp",
            "nombre_tipo": "Elementos plásticos",
            "nombre_zona": "Edif. de la Facultad de Humanidades y Educación"
        }
    ]
}

And we would have to cast it to an array to be able to manipulate it with a method like:

$.parseJSON(data);

If we want to bring a JSON through AJAX already cast as an array to be able to manipulate it easily:

$.getJSON(url, function( data ) {
  console.log("data",data);
});

The difference

Now returns the data as an array instead of a string.

data 
Object {aaData: Array[2]}
aaData: Array[2]
0: Object
apellido_autor: "Arp"
id: "132"
nombre_autor: "Jean"
nombre_tipo: "Escultura"
nombre_zona: "Plaza Cubierta del Rectorado"
__proto__: Object
1: Object
apellido_autor: "Arp"
id: "133"
nombre_autor: "Jean"
nombre_tipo: "Elementos plásticos"
nombre_zona: "Edif. de la Facultad de Humanidades y Educación"

What is the objective of passing data in the request?

If we are interested in obtaining a list given one or a series of identifiers, we must use the data parameter indicating the name of the parameter and its value; If there are several, the parameters must be separated by commas (,):

data : {
	id : 5,
	nombre : 'juan'
},

How to submit a form via AJAX?

If we want to send a form via AJAX, we can use the serialize() method provided by jQuery that we have already talked about on another occasion: this is how serialize works in jQuery.

$.ajax({
type : "GET",
data: $("form").serialize(),
url : url,
success : function(data) {
console.log("data",data);
},
error : function(objXMLHttpRequest) {
console.log("error",objXMLHttpRequest);
}
});

Ajax methods in jQuery

In case you do not want to use the $.ajax method, you can use other methods to save us some lines of JavaScript and that will also allow us to create more concise and descriptive code:

$.get Makes a GET request to a given URL.
$.post Makes a POST request to a given URL.
$.getJSON Makes a GET request to a given URL and expects the returned data to be JSON; If the data returned is not JSON, then the script will fail.

Regarding the arguments that you must establish, they are the following:

url The URL to which the request is to be made; Its value is mandatory since without the URL there is no resource to generate.
data The information to be sent to the server using GET or POST; Its use is optional and can be either an object or a data string: foo=bar&baz=bim).
success callback An optional but practically necessary function that is called if and only if the query was successful and from here we can access the data and manage it.
error callback This function is optional and is executed in case the request or query was not successful.
data type The type of data expected to be received from the server. Its value is optional.

// Get query with parameter passing and data returned in plain text
$.get('/user_data.php', { user_id : <?php echo $user_id >?}, function(data) {
    console.log(data);
});
 
// Get query with parameter passing and data returned in plain text
$.getJSON('/pais_json.php', function(json) {
     console.log(json);
});

Synchronous VS Asynchronous with AJAX

An interesting point about AJAX technology is that it is asynchronous; That is, the AJAX is executed without interrupting the rest of the JavaScript code; this can be an inconvenience on some occasions depending on the circumstances or what we want to do:

$.ajax({
type : "GET",
url : url,
success : function(data) {
console.log("msj1","esto se ejecutará de último");
},
error : function(objXMLHttpRequest) {
console.log("error",objXMLHttpRequest);
}
});
console.log("msj2","esto se ejecutará antes del ajax");

Return messages in the following order:

msg2 this will be executed before the ajax msg1 this will be executed last

Since AJAX does not "block" the rest of the JavaScript by default it does not stop the execution of the remaining JavaScript.

If we want the JavaScript to be "blocked" or stopped by default, we must use the async parameter set to false.

$.ajax({
type : "GET",
async : false,
url : url,
success : function(data) {
console.log("msg1","this will be executed first");
},
error : function(objXMLHttpRequest) {
console.log("error",objXMLHttpRequest);
}
});
console.log("msg2","this will be executed after ajax");

msg1 this will be executed first msg2 this will be executed after the ajax

Functions and parameters of the $.ajax method

The $.ajax method has several configuration options that we can use to adapt the script to our needs; you can check the full list in jQuery Ajax; Among the main ones we have:

async Establishes whether the request will be asynchronous or not; by default the value is true; setting the value to false will block the execution of the code until the request finishes; It is ideal to set it to false for when we want the returned data to be set in a global variable or something similar.
data Sets the data to be sent to the server using the same considerations that we explained previously.
jsonp This parameter is very useful and allows you to indicate whether the returned data will be in JSON format or not.
type This parameter allows you to establish whether the query or request will be through GET (by default) or another such as POST
url With this parameter, establish the URL of the resource to which the request will be made.
complete It is a function that, like success, is the callback function that is executed when the request finished successfully.
error This function is executed when an error occurs in the request.

Bonus: Promise functions: Async/Await to the rescue

So far we have seen how to perform the "traditional" callback where we have a function that runs in parallel asynchronously, brings data, and we do something with that data such as filling a list, a table, etc.; but we can take all this to another level, giving a higher level of embedding with our code through promise functions.

Promise functions allow you to manage flow and handle errors.

In addition to improving the flow in our app, promises allow us to "handle" errors or handle them in a simpler way using the well-known try and catch; To use the promise functions we must add a pair of reserved words called async and await:

function getDepartamentosJson(pais_id) {
    return $.getJSON("/clientes/j_departamento_by_pais_id/"+pais_id);
}

async function getDepartamentos() {
    try {
      var departamentos = await getDepartamentosJson(1);

//          departamentos = jQuery.parseJSON(departamentos);
      if(departamentos.length == 0) throw new Error('Sin data');

       // hacer otra cosa
       return departamentos;
    } catch(e) {
      console.log(e)
    }
}

As we see in the previous code, our code has a synchronous code structure but in reality it is asynchronous, since when the data getDepartamentosJson() returns the function getDepartamentos() will be executed and all this thanks to the async reserved word that we placed in the function and await that indicates that the getDepartamentos() function will continue to execute once the getDepartamentosJson() function finishes executing.

Links of interest

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.