Categories
JavaScript Answers

How to Resize Then Crop an Image in the HTML5 Canvas with JavaScript?

Sometimes, we want to resize then crop an image in the HTML5 canvas with JavaScript.

In this article, we’ll look at how to resize then crop an image in the HTML5 canvas with JavaScript.

Resize Then Crop an Image in the HTML5 Canvas with JavaScript

To resize then crop an image in the HTML5 canvas with JavaScript, we can call drawImage with several arguments.

For instance, we can write:

<canvas style='width: 200px; height: 200px'></canvas>

to add a canvas element.

Then, we write:

const image = new Image()
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d');
image.src = 'https://picsum.photos/500';
image.onload = () => {
  ctx.drawImage(
    image,
    20, 20,
    50, 50,
    20, 20,
    100, 100
  );
}

We create an image with the Image constructor.

Then we select the canvas element with document.querySelector.

And then we call getContext to get the context.

Next, we set the src property of the image to the image’s URL.

Then we set the onload property to a function that calls drawImage with the image to draw it.

The 2rd and 3th arguments of drawImage are the x and y coordinates of the top left corner of the source image to clip.

The 4th and 5th arguments of drawImage is the width and height of the area of the source image to clip.

The 6th and 7th arguments of drawImage is the x and y coordinates of the source image on the canvas.

And the last 2 arguments are the width and height of the destination image on the canvas.

Now we should see the cropped and resized image displayed on the canvas.

Conclusion

To resize then crop an image in the HTML5 canvas with JavaScript, we can call drawImage with several arguments.

Categories
JavaScript Answers

How to Split an Array into Array Pairs in JavaScript?

Sometimes, we want to split an array into array pairs in JavaScript.

In this article, we’ll look at how to split an array into array pairs in JavaScript.

Split an Array into Array Pairs in JavaScript

To split an array into array pairs in JavaScript, we can use the JavaScript array’s reduce method.

For instance, we can write:

const initialArray = [2, 3, 4, 5, 6, 4, 3, 5, 5]
const newArr = initialArray.reduce((result, value, index, array) => {
  if (index % 2 === 0) {
    return [...result, array.slice(index, index + 2)];
  }
  return result
}, []);
console.log(newArr)

We have the initialArray that we want to split into chunks of 2.

To do this, we call reduce with a callback that returns the result array that’s created from the result array spread into a new array and an array with the next 2 items in the list if index is event.

We get the next 2 items with the slice with index and index + 2 as the indexes.

Otherwise, we just return result.

The 2nd argument is an empty array so result is always an array.

As a result, newArr is:

[
  [
    2,
    3
  ],
  [
    4,
    5
  ],
  [
    6,
    4
  ],
  [
    3,
    5
  ],
  [
    5
  ]
]

Conclusion

To split an array into array pairs in JavaScript, we can use the JavaScript array’s reduce method.

Categories
JavaScript Answers

New JavaScript Features Coming in ES2020 That You Can Use Now (Part 2)

Since 2015, the JavaScript is evolving fast with lots of new features coming out in each iteration. New versions of the JavaScript language specification have been updated yearly, with new language feature proposals being finalized faster than ever.

This means that new features are getting incorporated into modern browsers and other JavaScript run-time engines like Node.js at a pace that we haven’t seen before. In 2019, there are many new features that are in the ‘Stage 3’ phase, which means that it’s very close to being finalized and browsers are getting support for these features now.

If we want to use them for production code, we can use something like Babel to transpile them to older versions of JavaScript so they can be used in older browsers like Internet Explorer if needed.

In this article, we’ll look at static fields and methods in classes and using the await keyword at the top level in regular code and module exports.

Static Fields and Methods in Classes

Static fields in classes is a new feature that’s coming soon to browsers and Node.js. It lets us add static fields for classes that do not need an instance of the class to be created to be accessed. They can both be private or public. It’s a handy replacement for enums. For example, with the latest proposal, we can write a class with static variables like in the following example:

class Fruit {
  static orange = 'orange';
  static grape = 'grape';
  static banana = 'banana';
  static apple = 'apple';

  static #secretPear = 'pear';

}

console.log(Fruit.orange);
console.log(Fruit.grape);
console.log(Fruit.banana);
console.log(Fruit.apple);

The example above should output:

orange
grape
banana
apple

If we try to access secretPear from outside the class, like in the following code:

console.log(Fruit.#secretPear);

We’ll get ‘Uncaught SyntaxError: Private field ‘#secretPear’ must be declared in an enclosing class.’

The keyword static is already working with methods in the classes since ES6. For example, we can declare a static method within a class by using the static keyword like in the following code:

class ClassStatic {
  static staticMethod() {
    return 'Static method has been called.';
  }
}

console.log(ClassStatic.staticMethod());

We should get ‘Static method has been called’ from the console.log output. As we can see the staticMethod method was called without instantiating the class ClassStatic class just like we expected. Static methods can also be private, we just add a # sign before the name of the method to make it private. For example, we can write the following code:

class ClassStatic {
  static #privateStaticMethod(){
    return 'Static method has been called.';
  }

  static staticMethod() {
    return ClassStatic.#privateStaticMethod();
  }
}

console.log(ClassStatic.staticMethod());

In the code above, we called the privateStaticMethod from the staticMethod to get the value of the return value from privateStaticMethod in staticMethod. Then when we call staticMethod by running ClassStatic.staticMethod() then we get ‘Static method has been called.’ However, we can’t call privateStaticMethod directly from outside the class, so if we run something like:

class ClassStatic {
  static #privateStaticMethod(){
    return 'Static method has been called.';
  }

  static staticMethod() {
    return ClassStatic.#privateStaticMethod();
  }
}

console.log(ClassStatic.#privateStaticMethod());

Then we will get an error. Also, note that we aren’t using this to access the privateStaticMethod , we used the class name ClassStatic to do it. If we use this to call it, as in this.#privateStaticMethod() , we’ll get an error or undefined depending on the Babel version we’re using. The static keyword for variables is partially supported within browsers. Chromium browsers like Chrome and Opera support it. Also, Node.js supports this keyword. Other browsers do not support it yet, so we’ve to use Babel to convert it into older JavaScript code for it to run on other browsers.

Top Level await

Currently, the await keyword can only be used inside async functions, which are functions that return promises. If we use the await keyword outside of an async function, we’ll get an error like ‘Cannot use keyword ‘await’ outside an async function’ and our program won’t run. Now we can use the await keyword without it being inside an async function. For example, we can use it with the following code:

const promise1 = new Promise((resolve)=>{
  setTimeout(()=> resolve('promise1 resolved'), 1000);
})

const promise2 = new Promise((resolve)=>{
  setTimeout(()=> resolve('promise2 resolved'), 1000);
})

const val1 = await promise1;
console.log(val1);
const val2 =  await promise2;
console.log(val2);

Then when we run this code above in Chrome, we’ll get:

promise1 resolved
promise2 resolved

With top-level await, we can run asynchronous code however we like, and we don’t have to go back to using the long-winded then function chaining with callbacks passed into each then function call. This is very clean and we don’t have to wrap it inside an async IIFE (immediately invoked function expression) to run it if we don’t want to declare a named function.

Another good thing about top-level await is that we can export it directly. This means that when the module exports something that has the await keyword, it will wait for the promise being the await keyword to resolve before running anything. On the surface, it acts as if it’s imported synchronously as usual, but underneath, it actually waits for the promise in the export expression to resolve. For example, we can write:

const promise1 = new Promise((resolve)=>{
  setTimeout(()=> resolve('promise1 resolved'), 1000);
})
export const val1 = await promise1;

When we import module1.js in module2.js :

import { val1 } from './module1';
console.log(`val1);

Then we can see the value of val1 logged as if it’s running synchronously, waiting for promise1 to resolve.

Conclusion

Static fields in classes is a new feature that’s coming soon to browsers and Node.js. It lets us add static fields for classes that do not need an instance of the class to be created to be accessed. They can both be private or public. It’s a handy replacement for enums.

Static methods have existed since ES6 and so it can be used now and has widespread support. Using the await keyword at the top level in regular code and module exports is very handy once it’s a finalized feature. It lets us use await to write asynchronous code outside of async functions, which is much cleaner than using then with callbacks.

Also, it can let us export the resolved value of asynchronous code and then import it and it use it in other modules as if it was synchronous code.

Categories
JavaScript Answers

Why Do We Need Strict Mode in JavaScript?

Strict mode is an important part of modern JavaScript. It is a mode that lets us opt-in to a more restricted syntax of JavaScript.

The semantics of strict mode is different from the old “sloppy mode” of JavaScript that has a looser syntax and makes errors in code that are silenced. This means that errors are ignored and the code might run with unexpected results.

Strict mode makes several changes to JavaScript semantics. It eliminates silent errors and instead throws them so that the code won’t run with errors in the code.

It will also point out mistakes that prevent JavaScript engines from doing optimizations. Also, it prohibits features that are likely to be defined in future versions of JavaScript.

Strict mode can be applied to individual functions or the whole script. It can’t be applied only to statements or other blocks enclosed in curly braces. To make a script use strict mode, we add the statement "use strict" or 'use strict' at the top of the script before any other statements.

If we have some scripts that use strict mode and others that don’t, then we might have scripts that use strict mode that are concatenated with other scripts that don’t use strict mode.

This means that code that doesn’t use strict mode might have been made to use strict mode when it’s concatenated together. The reverse is also true. So, it’s best not to mix them together.

We can also apply this to functions. To do this, we add the statement "use strict" or 'use strict' inside the functions on the top of the body, before any other statements. It’s applied to everything inside, including functions that are nested in the function that uses strict mode.

For example:

const strictFunction = ()=>{
  'use strict';
  const nestedFunction = ()=>{
    // this function also uses strict mode
  }
}

JavaScript modules, introduced in ES2015, have strict mode automatically enabled, so no statement is needed to enable it.

Changes in Strict Mode

Strict mode changes both the syntax and run time behavior of code that uses it. Mistakes in code are converted to errors as syntax errors that are thrown in run time, simplify how particular variables are computed, changes that simplify the eval function and the arguments object, and changes that might be implemented in future ES specification.

Converting Mistakes to Errors

Mistakes are converted to errors. They were previously accepted in non-strict mode. Strict mode restricts the use of error syntax and will not let the code run with errors in place.

It makes creating global variables hard by not letting us declare variables with var, let, or const, so creating variables without declaring them with those keywords won’t work. For example, the following code will throw a ReferenceError:

'use strict';
badVariable = 1;

We can’t run the code above in strict mode because this code will create a global variable badVariable if strict mode is off. Strict mode prevents this to prevent the creation of global variables accidentally.

Any code that silently fails will now throw an exception. This includes any invalid syntax that was ignored silently before.

For example, we can’t not assign to read-only variables like arguments, NaN, or eval with strict mode on.

Any assignment to read-only properties like non-writable global properties, assignment of getter-only properties, and assigning things to properties on non-extendable objects will throw an exception in strict mode.

Below are some examples of syntax that will fail with strict mode on:

'use strict';

let undefined = 5;
let Infinity = 5;

let obj = {};
Object.defineProperty(obj, 'foo', { value: 1, writable: false });
obj.foo = 1

let obj2 = { get foo() { return 17; } };
obj2.foo = 2

let fixedObj = {};
Object.preventExtensions(fixedObj);
fixed.bar= 1;

All of the examples above will throw a TypeError. undefined and Infinity are non-writable global objects. obj is a non-writable property.

obj2’s foo property is a getter only property and so cannot be set. fixedObj was prevented from adding more properties to it with the Object.preventExtensions method.

Also, deleting undeletable properties will throw a TypeError when there is code attempting to do so. For example:

'use strict';
delete `Array`.prototype

This will throw a TypeError.

Strict mode also disallows duplicate property names in an object before ES6 is introduced, so the following example will throw a syntax error:

'use strict';
var o = { a: 1, a: 2 };

Strict mode requires that function parameter names are unique. Without strict mode, if two parameters have the name one, then the one defined later will be accepted as the parameter’s value when arguments are passed in.

With strict mode, having multiple function parameters with the same name is no longer allowed, so the following example will fail to run with a syntax error:

const multiply = (x, x, y) => x*x*y;

Octal syntax is also not allowed in strict mode. It isn’t part of the specification, but it’s supported in browsers by prefixing octal numbers with a 0.

This confuses developers as some may think that the 0 preceding the number is meaningless. Therefore, strict mode disallows this syntax and will throw a syntax error.

Strict mode also prevents the use of syntax that makes optimizations difficult. It needs to know that a variable is actually stored at the location that it thinks it’s stored at before doing optimization, so we have to prevent the kind of syntax that stops optimizations from happening.

One example of this is the with statement. If we use it, it prevents the JavaScript interpreter from knowing which variable or property you’re referring to, as it’s possible to have a variable with the same name inside or outside the with statement.

If we have something like the following code:

let x = 1;
with (obj) {
  x;
}

Then, JavaScript wouldn’t know if the x inside the with statement is referring to the x variable or the property of obj, obj.x.

Therefore, the memory location of x is ambiguous. So, strict mode prevents the with statement from being used. If we have strict mode like the following:

'use strict';
`let x = 1;
with (obj) {
  x;
}`

Then the code above will have a syntax error.

Another thing that strict mode prevents is the declaration of variables inside an eval statement.

For example, without strict mode, eval('let x') would declare the variable x into the code. This lets people hide variable declarations in strings that might override the same variable declaration that’s outside the eval statement.

To prevent this, strict mode disallows variable declarations in the string argument that we pass into an eval statement.

Strict mode also prohibits deletion of plain variable names, so the following will throw a syntax error:

'use strict';

let x;
delete x;

Prohibiting Invalid Syntax

Invalid syntax of eval and argument isn’t allowed in strict mode.

This means that any manipulation done to them that isn’t allowed, like assigning new values to them or using them as names of variables, functions, or parameters in functions.

The following are examples of invalid uses of eval and the argument object that isn’t allowed:

'use strict';
eval = 1;
arguments++;
arguments--;
++eval;
eval--;
let obj = { set p(arguments) { } };
let eval;
try { } catch (arguments) { }
try { } catch (eval) { }
function x(eval) { }
function arguments() { }
let y = function eval() { };
let eval = ()=>{ };
let f = new Function('arguments', "'use strict'; return 1;");

Strict mode doesn’t allow an alias for the arguments object to be created and set with new values via the alias.

Without strict mode, if the first parameter of a function is a, then setting a also sets arguments[0]. With strict mode, the arguments object will always have the list of arguments that the function is called with.

For example, if we have:

const fn = function(a) {
  'use strict';
  a = 2;
  return [a, arguments[0]];
}

console.log(fn(1))

Then we should see [2,1] logged. This is because setting a to 2 doesn’t also set arguments[0] to 2.

Performance Optimizations

Also, there’s no more support for arguments.callee. Without strict mode, all it does is return the name of the function that’s being called that the arguments.callee is in.

It prevents optimizations like inline functions because arguments.callee requires that a reference to the un-inlined function is available if arguments.callee is accessed. Therefore, with strict mode, arguments.callee now throws a TypeError.

With strict mode, this will not be forced into always being an object. If a function’s this is bound, with call, apply, or bind to any non-object type, like primitive types of undefined, null, number, boolean, etc, then they must be forced into being objects.

If the context of this is switched to a non-object type, then the global window object will take its place. This means that the global object is exposed to the function that’s being called with this being bound to non-object types.

For example, if we run the following code:

'use strict';

function fn() {
  return this;
}
console.log(fn() === undefined);
console.log(fn.call(2) === 2);
console.log(fn.apply(null) === null);
console.log(fn.call(undefined) === undefined);
console.log(fn.bind(true)() === true);

All the console logs will be true, as the this inside the function isn’t automatically converted into the window global object when this is changed to something that has a non-object type.

Security Fixes

In strict mode, we also don’t allow the function’s caller and arguments to be exposed to the public since caller may expose the function that calls the function that the function’s caller property accessed.

The arguments have arguments that are passed in when the function is called. For example, if we have a function called fn, then through fn.caller, we can see the function that called fn, and through fn.arguments, we can see the arguments that were passed into fn when the call to fn is made.

This is a potential security hole that is eliminated by prohibiting access to these two properties of the function.

function secretFunction() {
  'use strict';
  secretFunction.caller;
  secretFunction.arguments;
}
function restrictedRunner() {
  return secretFunction();
}
restrictedRunner();

In the example above, we can’t access secretFunction.caller and secretFunction.arguments with strict mode as people may use it to get the call stack of functions. A TypeError will be thrown if we run that code.

Identifiers that will become restricted keywords in future versions of JavaScript will not be allowed to be used for identifiers like variable or property names.

The following keywords won’t be allowed to be used for defining our identifiers in code. implements, interface, let, package, private, protected, public, static, and yield.

With ES2015 or later, these have become reserved words, so they definitely cannot be used for naming variables and object properties without strict mode.

Strict mode has been a standard for a few years. Browser support for it is common, and only old browsers like Internet Explorer may have problems with it.

Other browsers shouldn’t have problems with working with strict mode. Therefore, it should be used to prevent mistakes and avoiding security hazards like exposing call stacks or declaring new variables in eval.

Also, it eliminates silent errors and instead throws them so that the code won’t run with errors in the code. It will also point out mistakes that prevent JavaScript engines to do optimizations.

Also, it prohibits features that are likely to be defined in future versions of JavaScript.

Categories
JavaScript Answers

Using Promises for Async Programming in JavaScript

Because JavaScript is a single-threaded language, synchronous code can only be executed one line at a time. This means that if there’s synchronous code that runs longer than instantaneously, then it will stop the rest of the code from running until whatever is being run is finished. To prevent code that runs for an indeterminate amount of time from holding up other code from running, we need to have asynchronous code.


Promises

To do this in JavaScript, we can use promises in our code. Promises are objects that represent a process that runs for an indeterminate amount of time and may result in success or failure. To create promises in JavaScript, we use a Promise object that’s a constructor for creating promises. The Promise constructor takes a function called the executor function that has the resolve and reject parameters. Both parameters are functions that we call to either fulfill the promise (which means end it successfully with some value) or to reject the promise (which means returning some error value and marking the promise as failed). The function’s return value is ignored. Therefore, promises can’t return anything other than promises.

For example, we can define a promise in JavaScript like in the following code:

const promise = new Promise((resolve, reject) => {  
  setTimeout(() => resolve('abc'), 1000);  
});

The code above creates a promise that fulfills the promise with the value abc after one second. Because we’re running setTimeout inside the executor function to resolve the promise with the value abc in one second, it’s asynchronous code. We can’t return the value abc within the callback function of setTimeout, so we have to call resolve('abc') to get the resolved value back. We can access the resolved value of the fulfilled promise by using the then function. The then function takes a callback function that takes the resolved value of the fulfilled promise as a parameter. You can get the value there and do what you want with it. For example, we can do something like:

const promise = new Promise((resolve, reject) => {  
  setTimeout(() => resolve('abc'), 1000);  
});

promise.then((val) => {  
  console.log(val);  
})

When we run the code above, we should see abc logged. As we can see, the promise will supply the value when the promise is fulfilled with a call to the resolve function.

A promise has three states. It can be pending, which means that the promise has been fulfilled or rejected. It can be fulfilled, which means that the operation completed successfully. Or it can be rejected, which means that the promise operation failed.

A pending promise can either be fulfilled with a value or be rejected with some error. When a promise is fulfilled, then the corresponding resolve value is picked up by the then function and the callback function passed into the then function is called. If a promise is rejected, then we can optionally catch the error with the catch function, which also takes a callback function with the error. Both the then and catch functions return promises, so they can be chained together.

For example, we can write something like:

const promise = (num) => {  
  return new Promise((resolve, reject) => {  
    setTimeout(() => {  
      if (num === 1) {  
        resolve('resolved')  
      } else {  
        reject('rejected')  
      }  
    }, 1000);  
  });  
}

promise(1)  
  .then((val) => {  
    console.log(val);  
  })  
  .catch((error) => {  
    console.log(error);  
  })promise(2)  
  .then((val) => {  
    console.log(val);  
  })  
  .catch((error) => {  
    console.log(error);  
  })

In the code above, we have a function promise that returns a JavaScript promise that fulfills the promise with the value resolved when num is 1, and reject the promise with error rejected otherwise. So we run:

promise(1)  
  .then((val) => {  
    console.log(val);  
  })  
  .catch((error) => {  
    console.log(error);  
  })

Then the then function runs, the promise returned by the promise(1) function call is fulfilled since num is 1, and the resolved value is available set in val. So when we run console.log(val) we get resolved logged. When we run the code below:

promise(2)  
  .then((val) => {  
    console.log(val);  
  })  
  .catch((error) => {  
    console.log(error);  
  })

Then the catch function runs because the promise returned by the promise(2) function call is rejected, and the rejected error value is available set in error. So when we run console.log(error) we get rejected logged.

A JavaScript promise object has the following properties: length and prototype. The length always has its value set to 1 for the number of constructor arguments, which is always one. The prototype property represents the prototype of the promise object.

A promise also has the finally method to run code that’s run no matter whether the promise is fulfilled or rejected. The finally method takes a callback function as an argument, where any code that you want to run, regardless of the outcome of the promise, is run. For example, if we run:

Promise.reject('error')  
  .then((value) => {  
    console.log(value);  
  })  
  .catch((error) => {  
    console.log(error);  
  })  
  .finally(() => {  
    console.log('finally runs');  
  })

Then we get error and finally runs logged because the original promise was rejected with the reason error. Then whatever code in the callback of the finally method runs.

The main benefit of using promises for writing asynchronous code is that we can use them to run asynchronous code sequentially. To do this, we can chain promises with the then function. The then function takes a callback function that runs when the promise is fulfilled. It also takes a second argument when the promise is rejected. To chain promises, we have to return another promise as the return value of the first callback function of the then function. It can return other values, like nothing, if we don’t want to chain another promise to the existing promise. We can return a value, which will be resolved and the value retrievable in the next then function. It can also throw an error. Then the promise returned by then gets rejected with the thrown error as the value. It can also return an already fulfilled or rejected promise, which will get the fulfilled value when a then function is chained after it or get an error reason in the callback of the catch function.

For example, we can write the following:

Promise.resolve(1)  
  .then(val => {  
    console.log(val);  
    return Promise.resolve(2)  
  })  
  .then(val => {  
    console.log(val);  
  })Promise.resolve(1)  
  .then(val => {  
    console.log(val);  
    return Promise.reject('error')  
  })  
  .then(val => {  
    console.log(val);  
  })  
  .catch(error => console.log(error));Promise.resolve(1)  
  .then(val => {  
    console.log(val);  
    throw new Error('error');  
  })  
  .then(val => {  
    console.log(val);  
  })  
  .catch(error => console.log(error));

In the first example, we chained the promises and they all resolve to a value. All the promises were already resolved into values. In the second and last examples, we reject the second promise or throw an error. They both do the same thing. The second promise is rejected, and the error reason will be logged in the callback of the catch function. We can also chain pending promises, like in the following code:

const promise1 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(1), 1000);  
});

const promise2 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(2), 1000);  
});

promise1  
  .then(val => {  
    console.log(val);  
    return promise2;  
  })  
  .then(val => {  
    console.log(val);  
  })  
  .catch(error => console.log(error));

The callback of the first then function returned promise2, which is a pending promise.


Methods

JavaScript promises have the following methods.

Promise.all(iterable)

Promise.all takes an iterable object that lets us run multiple promises in parallel in some computers and serially in other computers. This is handy for running multiple promises that don’t depend on each other’s values. It takes in an iterable with a list of promises, usually an array, and then returns a single Promise that’s resolved when the promises that are in the iterable are resolved.

For example, we can write code like the following to run multiple promises with Promise.all:

const promise1 = Promise.resolve(1);  
const promise2 = 2;  
const promise3 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(3), 1000);  
});  
Promise.all([promise1, promise2, promise3])  
  .then((values) => {  
    console.log(values);  
  });

If we run the code above, then the console.log should log [1,2,3]. As we can see, it only returns a resolved value after all the promises are fulfilled. If some of them are rejected, then we won’t get any resolved value. Instead, we will get whatever error value is returned by the rejected promises. It will stop at the first rejected promise and send that value to the callback of the catch function. For example, if we have:

const promise1 = Promise.resolve(1);  
const promise2 = Promise.reject(2);  
const promise3 = new Promise((resolve, reject) => {  
  setTimeout(() => reject(3), 1000);  
});  
Promise.all([promise1, promise2, promise3])  
  .then((values) => {  
    console.log(values);  
  })  
  .catch(error => {  
    console.log(error);  
  });

Then we get 2 logged from the console.log in the callback of the catch function.

Promise.allSettled

Promise.allSettled returns a promise that resolves after all the given promises are resolved or rejected. It takes an iterable object with a collection of promises, for example, an array of promises. The resolved value of the returned promise is an array of the final status of each promise. For example, suppose we have:

const promise1 = Promise.resolve(1);  
const promise2 = Promise.reject(2);  
const promise3 = new Promise((resolve, reject) => {  
  setTimeout(() => reject(3), 1000);  
});  
Promise.allSettled([promise1, promise2, promise3])  
  .then((values) => {  
    console.log(values);  
  })

If we run the code above, then we get an array with three entries, with each entry being an object that has the status and value properties for the fulfilled promises and an object that has the status and reason properties for the rejected promises. For example, the code above will log {status: “fulfilled”, value: 1}, {status: “rejected”, reason: 2}, {status: “rejected”, reason: 3} . The fulfilled status is logged for the successful promises and therejected status for the rejected ones.

Promise.race

The Promise.race method returns a promise that resolves to the resolved value of the promise that’s fulfilled first. It takes an iterable object with a collection of promises, for example, an array of promises. If the iterable passed in is empty, then the returned promise will forever be pending. If the iterable object contains one or more non-promise values or already settled promises, then Promise.race will return to the first of these entries. For example, if we have:

const promise1 = Promise.resolve(1);  
const promise2 = Promise.resolve(2);  
const promise3 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(3), 1000);  
});  
Promise.race([promise1, promise2, promise3])  
  .then((values) => {  
    console.log(values);  
  })

Then we see that 1 is logged. That’s because promise1 is the first one that’s resolved since it’s resolved instantaneously before the next lines are run. Likewise, if we have a non-promise value in the array that we pass in as the argument, like in the following code:

const promise1 = 1;  
const promise2 = Promise.resolve(2);  
const promise3 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(3), 1000);  
});  
Promise.race([promise1, promise2, promise3])  
  .then((values) => {  
    console.log(values);  
  })

Then we get the same thing logged since it’s the non-promise value in the array that we pass into the Promise.race method. Synchronous code always runs before the asynchronous code, so it doesn’t matter where the synchronous code is. If we have:

const promise1 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(1), 2000);  
});

const promise2 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(2), 1000);  
});

const promise3 = 3;  
Promise.race([promise1, promise2, promise3])  
  .then((values) => {  
    console.log(values);  
  })

Then we get 3 logged since setTimeout puts the callback function in the queue to be run later, so it’s going to be run later than the synchronous code.

Finally, if we have:

const promise1 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(1), 2000);  
}); 
 
const promise2 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(2), 1000);  
});

Promise.race([promise1, promise2])  
  .then((values) => {  
    console.log(values);  
  })

Then we get 2 in the console log because a promise that’s resolved in one second is going to be resolved earlier than a promise resolved in two seconds.

Promise.reject

Promise.reject returns a promise that’s rejected with a reason. It’s useful to reject a promise with an object that’s an instance of Error. For example, if we have the following code:

Promise.reject(new Error('rejected'))  
  .then((value) => {  
    console.log(value);  
  })  
  .catch((error) => {  
    console.log(error);  
  })

Then we get rejected logged.

Promise.resolve

Promise.resolve returns a promise that’s resolved to the value that’s passed into the argument of the resolve function. We can also pass in an object with the then property where the value of it is the callback function of a promise. If the value has a then method, then the promise will be fulfilled with the value fulfilled by the then function. That is, the first parameter of the function for the value of the then function is the same as resolve, and the second parameter is the same as reject. For example, we can write the following:

Promise.resolve(1)  
  .then((value) => {  
    console.log(value);  
  })

Then we get 1 logged since 1 is the value we passed into the resolve function to return the promise with resolved value 1.

If we pass in an object with a then method inside, like in the following code:

Promise.resolve({  
    then(resolve, reject) {  
      resolve(1);  
    }  
  })  
  .then((value) => {  
    console.log(value);  
  })

Then we get value 1 logged. That’s because the Promise.resolve function will run the then function, and the resolve parameter for the function set to the then property will be assumed to be a function that’s called the resolve function in a promise. If we instead called the reject function inside the then function in the passed-in object, then we get a rejected promise, like in the following code:

Promise.resolve({  
    then(resolve, reject) {  
      reject('error');  
    }  
  })  
  .then((value) => {  
    console.log(value);  
  })  
  .catch((error) => {  
    console.log(error);  
  })

In the code above, we get error logged since the promise is rejected.


Async and Await

With async and await, we can shorten the promise code. Before async and await, we had to use the then function and we had to put callback functions as an argument of all of our then functions. This makes the code long as we have lots of promises. Instead, we can use the async and await syntax to replace the then function and its associated callbacks. For example, we can shorten the following code from:

const promise1 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(1), 2000);  
});

const promise2 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(2), 1000);  
});

promise1  
  .then((val1) => {  
    console.log(val1);  
    return promise2;  
  })  
  .then((val2) => {  
    console.log(val2);  
  })

to:

const promise1 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(1), 2000);  
});  

const promise2 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(2), 1000);  
});

(async () => {  
  const val1 = await promise1;  
  console.log(val1)  
  const val2 = await promise2;  
  console.log(val2)  
})()

We replaced the then and callbacks with await. Then we can assign the resolved values of each promise as variables. Note that if we use await for our promise code, then we have to put async in the function signature as we did in the above example. To catch errors, instead of chaining the catch function at the end, we use the catch clause. Also, instead of chaining the finally function at the bottom to run code when a promise ends, we use the finally clause after the catch clause.

For example, we can write:

const promise1 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(1), 2000);  
});  
const promise2 = new Promise((resolve, reject) => {  
  setTimeout(() => reject('error'), 1000);  
});

(async () => {  
  try {  
    const val1 = await promise1;  
    console.log(val1)  
    const val2 = await promise2;  
    console.log(val2)  
  } catch (error) {  
    console.log(error)  
  } finally {  
    console.log('finally runs');  
  }})()

In the code above, we got the resolved value of the promise assigned to a variable instead of getting the value in the callback of the then function, like in the const response = await promise1 line above. Also, we used the try...catch...finally blocks to catch the errors of rejected promises and the finally clause instead of the finally function with a callback passed in to create code that runs no matter what happens to the promises.

Like any other function that uses promises, async functions always return promises and cannot return anything else. In the example above, we showed that we can chain promises in a much shorter way than with the then function with callbacks passed in as an argument.


Conclusion

With promises, we can write asynchronous code with ease. Promises are objects that represent a process that runs for an indeterminate amount of time and may result in success or failure. To create promises in JavaScript, we use a Promise object that’s a constructor for creating promises.

The Promise constructor takes a function called the executor function that has the resolve and reject parameters. Both parameters are functions that we call to either fulfill the promise (which means end it successfully with some value) or to reject the promise (which means returning some error value and marking the promise as failed). The function’s return value is ignored. Therefore, promises can’t return anything other than promises.

Promises are chainable since promises return promises. The then function of promises can throw an error, return resolved values, or return other promises that are pending, fulfilled, or rejected.