📜 ⬆️ ⬇️

Javascript asynchronous functions and this keyword

When using asynchronous functions in classes, there is often a problem when the body of the function cannot refer to the class object that calls the function. This is clearly seen in the example with Ajax (using jQuery):

function Loader() { this.load = function() { $.ajax({ url: '/test.php', success: function(data, textStatus, jqXHR) { //         console.log(this); // this    jQuery, //   success } }); } } (new Loader()).load(); 

To solve this problem, in the javascript there is a function apply , which allows you to call any function in the context of our object - i.e. this will be what we say. It remains only to make a callback function that will generate an asynchronous function:

 function cb(object, fnc) { return function() { return fnc.apply(object, arguments); } } 

object - the object that will be substituted in this
fnc - function performed
arguments - the standard object of the function arguments
')
Now the result will be as follows:

 function Loader() { this.load = function() { $.ajax({ url: '/test.php', success: cb(this, this.onLoad) }) } this.onLoad = function(data, textStatus, jqXHR) { console.log(this); // this     Loader } } (new Loader()).load(); 

As a function, it is not necessary to transfer the function of an object; you can create a function on the fly:

 cb(this, function(data, textStatus, jqXHR) { console.log(this); }); 

Saving the original object this


In the previous example, we lost an object that calls the success function (an internal jQuery object), but often there is a need to use the calling object. For example, in events of HTML elements:

 function Button() { this.render = function() { var submit = $('<button>').html('click me'); submit.bind('click', function(event) { //  this  HTML-,   console.log(this); }); submit.appendTo($('body')); } } (new Button()).render(); 

In this example, the click event of an HTML button element is raised. In order to save the object that calls the function (in this case, the HTML element of the button), the callback function takes the following form:

 function cb(object, fnc) { return function() { var args = [this]; for (var i in arguments) args.push(arguments[i]); return fnc.apply(object, args); } } 

Thus, the first argument of the function is passed to the calling object, and the remaining arguments are passed in the same order. The result will be as follows:

 function Button() { this.render = function() { var submit = $('<button>').html('click me'); submit.bind('click', cb(this, this.onClick)); submit.appendTo($('body')); } this.onClick = function(target, event) { console.log(this); // this     Button console.log(target); // HTML-,   } } (new Button()).render(); 

Source: https://habr.com/ru/post/141463/


All Articles