Functions
Basic Concepts +
JavaScript Function Syntax
A JavaScript function is defined with the function keyword, followed by a name, followed by parentheses (). Function names can contain letters, digits, underscores, and dollar signs (same rules as variables). The parentheses may include parameter names separated by commas:
(parameter1, parameter2, ...)
The code to be executed, by the function, is placed inside curly brackets: {}
function name(parameter1, parameter2, parameter3) { code to be executed }
Function parameters are the names listed in the function definition. Function arguments are the real values received by the function when it is invoked. Inside the function, the arguments (the parameters) behave as local variables. A Function is much the same as a Procedure or a Subroutine, in other programming languages.
Function Invocation
The code inside the function will execute when "something" invokes (calls) the function:
- When an event occurs (when a user clicks a button)
- When it is invoked (called) from JavaScript code
- Automatically (self invoked)
Function Return
When JavaScript reaches a return statement, the function will stop executing. If the function was invoked from a statement, JavaScript will "return" to execute the code after the invoking statement. Functions often compute a return value. The return value is "returned" back to the "caller":
Example
Calculate the product of two numbers, and return the result:
var x = myFunction(4, 3); // Function is called, return value will end up in x function myFunction(a, b) { return a * b; // Function returns the product of a and b }
The result in x will be: 12
Why Functions?
You can reuse code: Define the code once, and use it many times. You can use the same code many times with different arguments, to produce different results.
Example
Convert Fahrenheit to Celsius:
function toCelsius(fahrenheit) {
return (5/9) * (fahrenheit-32);
}
document.getElementById("demo").innerHTML = toCelsius(77);
The () Operator Invokes the Function
Using the example above, toCelsius refers to the function object, and toCelsius() refers to the function result.
Example
Accessing a function without () will return the function definition:
function toCelsius(fahrenheit) {
return (5/9) * (fahrenheit-32);
}
document.getElementById("demo").innerHTML = toCelsius;
Functions Used as Variable Values
Functions can be used the same way as you use variables, in all types of formulas, assignments, and calculations.
Example
Instead of using a variable to store the return value of a function:
var x = toCelsius(77);
var text = "The temperature is " + x + " Celsius";You can use the function directly, as a variable value:
var text = "The temperature is " + toCelsius(77) + " Celsius";
More.... - MDN
More... javascript.info
Function Invocation +
- The code inside a function is not executed when the function is defined.
- The code inside a function is executed when the function is invoked or called.
function myFunction(a, b) { return a * b; } var x = myFunction(5, 2); alert(x); // 10
- The function above does not belong to any object. But in JavaScript there is always a default global object.
- In HTML the default global object is the HTML page itself, so the function above "belongs" to the HTML page.
- In a browser the page object is the browser window. The function above automatically becomes a window function.
- Global variables, methods, or functions can easily create name conflicts and bugs in the global object.
myFunction()
andwindow.myFunction()
is the same function:
function myFunction(a, b) { return a * b; } window.myFunction(10, 2); // Will also return 20
this
as Global Object
- In JavaScript, the thing called
this
, is the object that "owns" the current code. - The value of
this
, when used in a function, is the object that "owns" the function. this
is not a variable. It is a keyword. You cannot change the value ofthis
- Invoking a function as a global function, causes the value of
this
to be the global object.
var x = myFunction(); // x will be the window object function myFunction() { return this; } alert(x) // [object Window]
Invoking a Function as a Method
In JavaScript you can define functions as object methods.
n JavaScript all functions are object methods.
IIf a function is not a method of a JavaScript object, it is a function of the global object
The following example creates an object (myObject), with two properties (firstName and lastName), and a method (fullName):
var myObject = { firstName:"John", lastName: "Doe", fullName: function () { return this.firstName + " " + this.lastName; } } myObject.fullName(); // Will return "John Doe"
The fullName
method is a function. The function belongs to the object. myObject
is the owner of the function.
The thing called this
, is the object that "owns" the JavaScript code. In this case the value of this
is myObject
.
Change the fullName
method to return the value of this
:
var myObject = { firstName:"John", lastName: "Doe", fullName: function () { return this; } } myObject.fullName(); // Will return [object Object] (the owner object)
this
to be the object itself.Invoking a Function with a Function Constructor
If a function invocation is preceded with the new
keyword, it is a constructor invocation.
It looks like you create a new function, but since JavaScript functions are objects you actually create a new object:
// This is a function constructor: function myFunction(arg1, arg2) { this.firstName = arg1; this.lastName = arg2; } // This creates a new object var x = new myFunction("John", "Doe"); x.firstName; // Will return "John"
- A constructor invocation creates a new object.
- The new object inherits the properties and methods from its constructor.
- The this keyword in the constructor does not have a value.
- The value of
this
will be the new object created when the function is invoked.
Function Statement VS Function Expressions +
The function
keyword can be used to define a function inside an expression.
function [name]([param1[, param2[, ..., paramN]]]) { statements }
Parameters
name
- The function name. Can be omitted, in which case the function is anonymous. The name is only local to the function body.
paramN
- The name of an argument to be passed to the function.
statements
- The statements which comprise the body of the function.
A function expression is very similar to and has almost the same syntax as a function statement. The main difference between a function expression and a function statement is the function name, which can be omitted in function expressions to create anonymous functions. A function expression can be used as a IIFE (Immediately Invoked Function Expression) which runs as soon as it is defined. See also the chapter about functions for more information.
The following example defines an unnamed function and assigns it to x
. The function returns the square of its argument:
var x = function(y) { return y * y; };
Named function expression
If you want to refer to the current function inside the function body, you need to create a named function expression. This name is then local only to the function body (scope). This also avoids using the non-standard arguments.callee
property.
var math = { 'factorial': function factorial(n) { if (n <= 1) return 1; return n * factorial(n - 1); } };
Function Declarations vs. Function Expressions+
What is a Function Declaration?
A Function Declaration defines a named function variable without requiring variable assignment. Function Declarations occur as standalone constructs and cannot be nested within non-function blocks. It’s helpful to think of them as siblings of Variable Declarations. Just as Variable Declarations must start with “var”, Function Declarations must begin with “function”.
function bar() { return 3; }
function Identifier ( FormalParameterListopt ) { FunctionBody }
The function name is visible within it’s scope and the scope of it’s parent (which is good because otherwise it would be unreachable)
function bar() { return 3; } bar() //3 bar //function
What is a Function Expression?
A Function Expression defines a function as a part of a larger expression syntax (typically a variable assignment ). Functions defined via Functions Expressions can be named or anonymous. Function Expressions must not start with “function” (hence the parentheses around the self invoking example below)
//anonymous function expression var a = function() { return 3; } //named function expression var a = function bar() { return 3; } //self invoking function expression (function sayHello() { alert("hello!"); })();
what’s Hoisting?
“Function declarations and function variables are always moved (‘hoisted’) to the top of their JavaScript scope by the JavaScript interpreter”. When a function declaration is hoisted the entire function body is lifted with it.
Do Function Expressions get Hoisted too?
That depends on the expression. Let’s look at the first expression in Question 2:
var bar = function() { return 3; };
The left hand side (var bar) is a Variable Declaration. Variable Declarations get hoisted but their Assignment Expressions don’t. So when bar is hoisted the interpreter initially sets var bar = undefined. The function definition itself is not hoisted.
Factory Function +
A factory function is any function which is not a class or constructor that returns a (presumably new) object. In JavaScript, any function can return an object. When it does so without the new keyword, it's a factory function.
Factory functions are a good way to more effectively group properties and functionality into objects. They’re basically just functions that return an object. Check it out:
function createPerson(name){ return { name: name, greet: function() {console.log("Hello, I'm" + this.name);} } } var person = createPerson("Jack Johnson");
Here, createPerson(name)returns an object literal that can now be used as a normal object. This method of creating objects beats out using raw object literals because you don’t have to copy and paste all the functions and properties of an object every time you want to declare a new instance of it. You can pass parameters to easily tweak objects you want to reuse with different properties. Factory functions provide an element of re-usability while retaining a lot of the flexibility you get with object literals.
Constructor Functions +
These functions are the most conventional way to create objects that use functionality from each other using prototypal inheritance. What is prototypal inheritance, you ask? Let me show you using constructor functions. Take the Person object from the last two examples:
function Person(name) { // 1 this.name = name; this.greet = function() { console.log("Hello, I'm " + this.name); } } //2 var person = new Person("Jack Johnson"); //3 console.log(Object.getPrototypeOf(person)); // Person {}
call() and apply() method +
call()
With predefined JavaScript call()
method, an object can use a method belonging to another object.
This example calls the fullName
method of person, using it on person1
:
var person = { fullName: function() { return this.firstName + " " + this.lastName; } } var person1 = { firstName:"John", lastName: "Doe", } var person2 = { firstName:"Mary", lastName: "Doe", } person.fullName.call(person1); // Will return "John Doe"
Adding call(person1) after fullname will indicate this
to person1 object.
var person = { fullName: function() { return this.firstName + " " + this.lastName; } } var person1 = { firstName:"John", lastName: "Doe", } var person2 = { firstName:"Mary", lastName: "Doe", } person.fullName.call(person2); // Will return "Mary Doe"
The call()
Method with Arguments
var person = { fullName: function(city, country) { return this.firstName + " " + this.lastName + "," + city + "," + country; } } var person1 = { firstName:"John", lastName: "Doe", } person.fullName.call(person1, "Oslo", "Norway");
apply()
The apply()
method is similar to the call()
method
var person = { fullName: function() { return this.firstName + " " + this.lastName; } } var person1 = { firstName: "Mary", lastName: "Doe", } person.fullName.apply(person1); // Will return "Mary Doe"
The Difference Between call()
and apply()
- The
call()
method takes arguments separately. - The
apply()
method takes arguments as an array.
apply()
method is very handy if you want to use an array instead of an argument list.
The apply()
method accepts arguments in an array:
var person = { fullName: function(city, country) { return this.firstName + " " + this.lastName + "," + city + "," + country; } } var person1 = { firstName:"John", lastName: "Doe", } person.fullName.apply(person1, ["Oslo", "Norway"]);
Closure +
A closure is the combination of a function and the lexical environment within which that function was declared.
Closure is when a function is able to remember and access its lexical scope even when that function is executing outside its lexical scope.
You can nest a function within a function. The nested (inner) function is private to its containing (outer) function. It also forms a closure. A closure is an expression (typically a function) that can have free variables together with an environment that binds those variables (that "closes" the expression).
A closure is an inner function that has access to the outer (enclosing) function’s variables—scope chain. The closure has three scope chains: it has access to its own scope (variables defined between its curly brackets), it has access to the outer function’s variables, and it has access to the global variables.
The inner function has access not only to the outer function’s variables, but also to the outer function’s parameters. Note that the inner function cannot call the outer function’s arguments object, however, even though it can call the outer function’s parameters directly.
Lexical scoping
function init() { var name = 'Mozilla'; // name is a local variable created by init function displayName() { // displayName() is the inner function, a closure alert(name); // use variable declared in the parent function } displayName(); } init();
init()
creates a local variable called name and a function called displayName()
. The displayName()
function is an inner function that is defined inside init()
and is only available within the body of the init()
function. The displayName()
function has no local variables of its own. However, because inner functions have access to the variables of outer functions, displayName()
can access the variable name declared in the parent function, init()
. However, the same local variables in displayName()
will be used if they exist.
<h2>JavaScript Closures</h2> <p>Counting with a local variable.</p> <button type="button" onclick="myFunction()">Count!</button> <p id="demo">0</p> <script> var add = (function () { var counter = 0; return function () {counter += 1; return counter;} })(); function myFunction(){ document.getElementById("demo").innerHTML = add(); } </script>
- The variable add is assigned the return value of a self-invoking function.
- The self-invoking function only runs once. It sets the counter to zero (0), and returns a function expression.
- This way add becomes a function. The "wonderful" part is that it can access the counter in the parent scope.
- This is called a JavaScript closure. It makes it possible for a function to have "private" variables.
- The counter is protected by the scope of the anonymous function, and can only be changed using the add function.
JavaScript Closures are not that scary! [ Explained in Bangla ]
Video Tuts by Learn with Sumit - Sept 1, 2020
More...
Immediately-Invoked Function Expressions (IIFEs) +
Immediately invoked function expressions may be written in a number of different ways.[5] A common convention is to enclose the function expression – and optionally its invocation operator – with the grouping operator,[6] in parentheses, to tell the parser explicitly to expect an expression. Otherwise, in most situations, when the parser encounters the function keyword, it treats it as a function declaration (statement), and not as a function expression.
(function () { /* ... */ })(); (function () { /* ... */ }()); (() => { /* ... */ })(); // With ES6 arrow functions (though parentheses only allowed on outside)
Passing variables into the scope is done as follows:
(function(a, b) { /* ... */ })("hello", "world");
An initial parenthesis is one case where the automatic semicolon insertion (ASI) in JavaScript can cause problems; the expression is instead interpreted as a call to the last term on the preceding line. In some styles that omit optional semicolons, the semicolon is placed in front of the parenthesis, and is known as a defensive semicolon. For example:
a = b + c ;(function () { // code })();
A lack of block scope means that variables defined inside, for example, a for loop will have their definition "hoisted" to the top of the enclosing function. Evaluating a function that depends on variables modified by the outer function (including by iteration) can be difficult. We can see this without a loop if we update a value between defining and invoking the function.
var v, getValue; v = 1; getValue = function () { return v; }; v = 2; getValue(); // 2
While the result may seem obvious when updating v
manually, it can produce unintended results when getValue()
is defined inside a loop.
Hereafter the function passes v
as an argument and is invoked immediately, preserving the inner function's execution context.
var v, getValue; v = 1; getValue = (function (x) { return function () { return x; }; })(v); v = 2; getValue(); // 1
This is equivalent to the following code
var v, getValue; v = 1; function f(x) { return function () { return x; }; }; getValue = f(v); v = 2; getValue(); // 1
IIFEs are also useful for establishing private methods for accessible functions while still exposing some properties for later use
// "counter" is a function that returns an object with properties, which in this case are functions. var counter = (function () { var i = 0; return { get: function () { return i; }, set: function (val) { i = val; }, increment: function () { return ++i; } }; })(); // These calls access the function properties returned by "counter". counter.get(); // 0 counter.set(3); counter.increment(); // 4 counter.increment(); // 5
If we attempt to access counter.i
from the global environment, it will be undefined, as it is enclosed within the invoked function and is not a property of counter. Likewise, if we attempt to access i
, it will result in an error, as we have not declared i
in the global environment.
Callback Function +
A callback is a function that is to be executed after another function has finished executing — hence the name ‘call back’.
In JavaScript, functions are objects. Because of this, functions can take functions as arguments, and can be returned by other functions. Functions that do this are called higher-order functions. Any function that is passed as an argument is called a callback function
Why do we need Callbacks?
For one very important reason — JavaScript is an event driven language. This means that instead of waiting for a response before moving on, JavaScript will keep executing while listening for other events. Lets look at a basic example:
function mySandwich(param1, param2, callback) { alert('Started eating my sandwich.\nIt has: ' + param1 + ', ' + param2); callback(); } mySandwich('ham', 'cheese', function() { alert('Finished eating my sandwich.'); });
Here we have a function called mySandwich and it accepts three parameters. The third parameter is the callback function. When the function executes, it spits out an alert message with the passed values displayed. Then it executes the callback function.
Notice that the actual parameter is just “callback” (without parentheses), but then when the callback is executed, it’s done using parentheses. You can call this parameter whatever you want, I just used “callback” so it’s obvious what’s going on.
The callback function itself is defined in the third argument passed to the function call. That code has another alert message to tell you that the callback code has now executed. You can see in this simple example that an argument passed into a function can be a function itself, and this is what makes callbacks possible in JavaScript.
Make the Callback Optional
One thing you’ll notice about jQuery callbacks is that they’re optional. This means if a method accepts a callback, it won’t return an error if a callback is not included. In our simple example, the page will return an error if we call the function without a callback, like this:
function mySandwich(param1, param2, callback) { alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2); callback(); } mySandwich('ham', 'cheese');
To make the callback optional, we can just do this:
function mySandwich(param1, param2, callback) { alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2); if (callback) { callback(); } } mySandwich('ham', 'cheese');
Now, since we’re checking to ensure the existence of callback, the function call won’t cause an error without it
Make Sure the Callback is a Function
Finally, you can ensure that whatever value is passed as the third argument is in fact a proper function, by doing this:
function mySandwich(param1, param2, callback) { alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2); if (callback && typeof(callback) === "function") { callback(); } } mySandwich('ham', 'cheese', 'vegetables');
A Note About Timing
Although it is true that a callback function will execute last if it is placed last in the function, this will not always appear to happen. For example, if the function included some kind of asynchronous execution (like an Ajax call or an animation), then the callback would execute after the asynchronous action begins, but possibly before it finishes.
Here’s an example that uses jQuery’s animate method:
function mySandwich(param1, param2, callback) { alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2); $('#sandwich').animate({ opacity: 0 }, 5000, function() { // Animation complete. }); if (callback && typeof(callback) === "function") { callback(); } } mySandwich('ham', 'cheese', function() { alert('Finished eating my sandwich.'); });
Notice that although the callback appears later in source order than the animation, the callback will actually execute long before the animation completes. In this case, solving this problem is easy: You just put the callback execution inside the animate method’s callback function (where it says “Animation complete”).
Problem When Using Methods With The this Object as Callbacks
When the callback function is a method that uses the this object, we have to modify how we execute the callback function to preserve the this object context. Or else the this object will either point to the global window object (in the browser), if callback was passed to a global function. Or it will point to the object of the containing method.
// Define an object with some properties and a method // We will later pass the method as a callback function to another function var clientData = { id: 094545, fullName: "Not Set", // setUserName is a method on the clientData object setUserName: function (firstName, lastName) { // this refers to the fullName property in this object this.fullName = firstName + " " + lastName; } } function getUserInput(firstName, lastName, callback) { // Do other stuff to validate firstName/lastName here // Now save the names callback (firstName, lastName); }
In the following code example, when clientData.setUserName is executed, this.fullName will not set the fullName property on the clientData object. Instead, it will set fullName on the window object, since getUserInput is a global function. This happens because the this object in the global function points to the window object
getUserInput ("Barack", "Obama", clientData.setUserName); console.log (clientData.fullName);// Not Set // The fullName property was initialized on the window object console.log (window.fullName); // Barack Obama
Use the Call or Apply Function To Preserve this
We can fix the preceding problem by using the Call or Apply function (we will discuss these in a full blog post later). For now, know that every function in JavaScript has two methods: Call and Apply. And these methods are used to set the this object inside the function and to pass arguments to the functions.
Call takes the value to be used as the this object inside the function as the first parameter, and the remaining arguments to be passed to the function are passed individually (separated by commas of course). The Apply function’s first parameter is also the value to be used as the this object inside the function, while the last parameter is an array of values (or the arguments object) to pass to the function.
This sounds complex, but lets see how easy it is to use Apply or Call. To fix the problem in the previous example, we will use the Apply function thus:
//Note that we have added an extra parameter for the callback object, called "callbackObj" function getUserInput(firstName, lastName, callback, callbackObj) { // Do other stuff to validate name here // The use of the Apply function below will set the this object to be callbackObj callback.apply (callbackObj, [firstName, lastName]); }
With the Apply function setting the this object correctly, we can now correctly execute the callback and have it set the fullName property correctly on the clientData object:
// We pass the clientData.setUserName method and the clientData object as parameters. The clientData object will be used by the Apply function to set the this object getUserInput ("Barack", "Obama", clientData.setUserName, clientData); // the fullName property on the clientData was correctly set console.log (clientData.fullName); // Barack Obama
We would have also used the Call function, but in this case we used the Apply function.
Multiple Callback Functions Allowed
We can pass more than one callback functions into the parameter of a function, just like we can pass more than one variable. Here is a classic example with jQuery’s AJAX function:
function successCallback() { // Do stuff before send } function successCallback() { // Do stuff if success message received } function completeCallback() { // Do stuff upon completion } function errorCallback() { // Do stuff if error received } $.ajax({ url:"http://fiddle.jshell.net/favicon.png", success:successCallback, complete:completeCallback, error:errorCallback });
synchronous callback, as it is executed immediately.
function greeting(name) { alert('Hello ' + name); } function processUserInput(callback) { var name = prompt('Please enter your name.'); callback(name); } processUserInput(greeting);
function one(x) { alert(x); } function two(var1, callback) { callback(var1); } two(2, one); // 2
we can also pass functions as parameters:
function sayHi(x) { console.log(x); } function sayBye() { console.log("Bye!") } sayHi(sayBye()); // "Bye!"
Synchronas and Asynchronas callback
JavaScript is synchronous. This means that it will execute your code block by order after hoisting. Before the code executes, var and function declarations are “hoisted” to the top of their scope.
JavaScript is synchronous by default and is single threaded. This means that code cannot create new threads and run in parallel.
This is an example of a synchronous code:
console.log('1') console.log('2') console.log('3')
This code will reliably log “1 2 3".
Asynchronous requests will wait for a timer to finish or a request to respond while the rest of the code continues to execute. Then when the time is right a callback will spring these asynchronous requests into action.
This is an example of an asynchronous code:
console.log('1') setTimeout(function afterTwoSeconds() { console.log('2') }, 2000) console.log('3')
This will actually log “1 3 2”, since the “2” is on a setTimeout
which will only execute, by this example, after two seconds. Your application does not hang waiting for the two seconds to finish. Instead it keeps executing the rest of the code and when the timeout is finished it returns to afterTwoSeconds.
javascript.info/callbacks
JavaScript Callback Functions - dashingd3js.com>
promises, async and await +
Introduction to Promises
- A promise is commonly defined as a proxy for a value that will eventually become available.
- Promises are one way to deal with asynchronous code, without writing too many callbacks in your code.
- Although they’ve been around for years, they were standardized and introduced in ES2015, and now they have been superseded in ES2017 by async functions.
- Async functions use the promises API as their building block, so understanding them is fundamental even if in newer code you’ll likely use async functions instead of promises.
- With Promises, we can defer execution of a code block until an async request is completed. This way, other operations can keep running without interruption.
Promises have three states:
- Pending: This is the initial state of the Promise before an operation begins
- Fulfilled: This means the specified operation was completed
- Rejected: The operation did not complete; an error value is usually thrown
The Promise object is created using the new keyword and contains the promise; this is an executor function which has a resolve and a reject callback. As the names imply, each of these callbacks returns a value with the reject callback returning an error object.
const promise = new Promise(function(resolve, reject) { // promise description })
Let’s create a promise:
const weather = true const date = new Promise(function(resolve, reject) { if (weather) { const dateDetails = { name: 'Cubana Restaurant', location: '55th Street', table: 5 }; resolve(dateDetails) } else { reject(new Error('Bad weather, so no Date')) } });
If weather
is true, resolve the promise returning the data dateDetails
, else return an error object with data Bad weather, so no Date
.
Using Promises
Using a promise that has been created is relatively straightforward; we chain .then()
and .catch()
to our Promise like so:
date .then(function(done) { // the content from the resolve() is here }) .catch(function(error) { // the info from the reject() is here });
Using the promise we created above, let's take this a step further:
const myDate = function() { date .then(function(done) { console.log('We are going on a date!') console.log(done) }) .catch(function(error) { console.log(error.message) }) } myDate();
Since the weather value is true, we call mydate()
and our console logs read:
We are going on a date! { name: 'Cubana Restaurant', location: '55th Street' table: 5 }
.then()
receives a function with an argument which is the resolve value of our promise. .catch returns the reject value of our promise.
Chaining Promises
Sometimes we may need to execute two or more asynchronous operations based on the result of preceding promises. In this case, promises are chained. Still using our created promise, let’s order an uber if we are going on a date.
So we create another promise:
const orderUber = function(dateDetails) { return new Promise(function(resolve, reject) { const message = `Get me an Uber ASAP to ${dateDetails.location}, we are going on a date!`; resolve(message) }); }
This promise can be shortened to:
const orderUber = function(dateDetails) { const message = `Get me an Uber ASAP to ${dateDetails.location}, we are going on a date!`; return Promise.resolve(message) }
We chain this promise to our earlier date operation like so:
const myDate = function() { date .then(orderUber) .then(function(done) { console.log(done); }) .catch(function(error) { console.log(error.message) }) } myDate();
Since our weather is true, the output to our console is:
Get me an Uber ASAP to 55th Street, we are going on a date!
Once the orderUber
promise is chained with .then
, subsequent .then
utilizes data from the previous one.
More .... - MDN
promises basics - javascript.info
Async and Await
An async function is a modification to the syntax used in writing promises. You can call it syntactic sugar over promises. It only makes writing promises easier.
An async function returns a promise -- if the function returns a value, the promise will be resolved with the value, but if the async function throws an error, the promise is rejected with that value. Let’s see an async function:
async function myRide() { return '2017 Dodge Charger'; }
and a different function that does the same thing but in promise format:
function yourRide() { return Promise.resolve('2017 Dodge Charger'); }
From the above statements, myRide()
and yourRide()
are equal and will both resolve to 2017 Dodge Charger
. Also when a promise is rejected, an async function is represented like this:
function foo() { return Promise.reject(25) } // is equal to async function() { throw 25; }
Await
Await is only used with an async function. The await keyword is used in an async function to ensure that all promises returned in the async function are synchronized, ie. they wait for each other. Await eliminates the use of callbacks in .then()
and .catch()
. In using async and await, async is prepended when returning a promise, await is prepended when calling a promise. try
and catch
are also used to get the rejection value of an async function. Let's see this with our date example:
async function myDate() { try { let dateDetails = await date; let message = await orderUber(dateDetails); console.log(message); } catch(error) { console.log(error.message); } }
Lastly we call our async function:
(async () => { await myDate(); })();
Note we used the ES6 arrow function syntax here.
developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await
More.... - MDN
More.. MDN
javascript.info/async-await
digitalocean.com/community/tutorials/js-async-functions
w3schools.com/js/js_async.asp
Arrow Function +
Arrow Funciton
let sum = (a, b) => a + b; /* The arrow function is a shorter form of: let sum = function(a, b) { return a + b; }; */ alert( sum(1, 2) ); // 3
If we have only one argument, then parentheses can be omitted, making that even shorter:
// same as // let double = function(n) { return n * 2 } let double = n => n * 2; alert( double(3) ); // 6
If there are no arguments, parentheses should be empty (but they should be present):
let sayHi = () => alert("Hello!"); sayHi();
Arrow functions can be used in the same way as Function Expressions.
let age = prompt("What is your age?", 18); let welcome = (age < 18) ? () => alert('Hello') : () => alert("Greetings!"); welcome(); // ok now
Multiline Arrow Function
let sum = (a, b) => { // the curly brace opens a multiline function let result = a + b; return result; // if we use curly braces, use return to get results }; alert( sum(1, 2) ); // 3
One common use case for arrow functions is array manipulation
const smartPhones = [ { name:'iphone', price:649 }, { name:'Galaxy S6', price:576 }, { name:'Galaxy Note 5', price:489 } ]; // ES5 var price = smartPhones.map(function(smartPhone) { return smartPhone.price; }); alert(price); // [649, 576, 489] // ES6 with arrow function const prices = smartPhones.map(smartPhone => smartPhone.price); alert(prices); // [649, 576, 489]
Here’s another example using the array filter method:
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; // ES5 var divisibleByThrreeES5 = array.filter(function (v){ return v % 3 === 0; }); // ES6 const divisibleByThrreeES6 = array.filter(v => v % 3 === 0);
Here’s a simple example of chaining promises
// ES5 aAsync().then(function() { returnbAsync(); }).then(function() { returncAsync(); }).done(function() { finish(); });
This code is simplified, and arguably easier to read using arrow functions:
// ES6 aAsync().then(() => bAsync()).then(() => cAsync()).done(() => finish);
More.... - MDN
Javascript call and apply explained
As an example, in the code below we call sayHi in the context of different objects: sayHi.call(user) runs sayHi providing this=user, and the next line sets this=admin:
function sayHi() { alert(this.name); } let user = { name: "John" }; let admin = { name: "Admin" }; // use call to pass different objects as "this" sayHi.call( user ); // John sayHi.call( admin ); // Admin