Categories
JavaScript JavaScript Basics

Where’s the Sleep Function in JavaScript?

If we try to search for the sleep function in JavaScript, we won’t find it. However, we can easily make one with existing functions.

setTimeout Function

There’s a setTimeout function that lets us run code after a specified number of milliseconds. We can use it to create our own sleep function.

Like most time-sensitive JavaScript code, it’s going to be asynchronous since this won’t hold up the main thread running our program.

We can create a function that runs code after a specified amount of time by writing:

const runLater = (delay) => {  
  setTimeout(() => {  
    console.log('bar');  
  }, delay)  
}

The runLater function will show the string 'bar' when we pass in the delay by in number of milliseconds.

If we run:

console.log('foo')  
runLater(100);  
console.log('baz')

We’ll see that we get:

foo  
baz  
bar

This is because the synchronous code, which are the first and last lines, are run first. The runLater(100) is queued up to be run in the next iteration of the event loop between the time when the first and last lines are run.

Then in the next iteration of the event loop, the code in the setTimeout callback runs, which will log 'baz' .

This means that if we want to run code in callbacks sequentially, we have to nest the callbacks. And too many callbacks create callback hell.

Promises

Therefore, the best way to run asynchronous JavaScript code sequentially is to use promises. We can create a promise with the setTimeout function by using the Promise constructor.

We can write the sleep function as follows:

const sleep = (delay) => {  
  return new Promise(resolve => {  
    setTimeout(resolve, delay)  
  });  
}

The sleep function returns a promise which resolves after the setTimeout callback, which is the resolve function is called after delay milliseconds.

A promise is asynchronous like the setTimeout callback. The good thing about it is that we can run them sequentially as they’re fulfilled.

Fulfilled means that the resolve method in the callback above is called. A promise can also be rejected with the reject function when an error occurs.

Using promises let us chain asynchronous code and run them sequentially.

We can do this cleanly with async functions. To define an async function, we use the async and await keywords as follows:

(async ()=>{  
  console.log('foo');  
  await sleep(2000);  
  console.log('bar');  
})();

If we run the code above, we should see that 'foo' is logged, then 2 seconds after that 'bar' is logged.

This will let us up time delayed code without hanging our app.

The number 2000 in the argument is in milliseconds, so it’ll wait 2 seconds before running the next line.

await tells the browser to hold off on executing the next line until the await line is resolved. We can put await in front of any promise to indicate that we should wait for the promise to resolve before continuing.

We can keep repeating this:

(async () => {  
  console.log('foo');  
  await sleep(2000);  
  console.log('bar');  
  await sleep(2000);  
  console.log('a');  
  await sleep(2000);  
  console.log('b');  
})();

But it gets repetitive. Fortunately, we can use loops to eliminate this repetition.

For-Await-Of Loop

We have the for-await-of loop which loops through iterable objects like arrays and array-like objects whether they’re synchronous or asynchronous.

To do this, we can write:

(async () => {  
  const arr = ['foo', 'bar', 'a', 'b'];  
  for await (let a of arr) {  
    console.log(a);  
    await sleep(2000);  
  }  
})();

The code above is much cleaner and it doesn’t matter how many things we want to loop through.

It’s important that we actually have promise code inside our async functions whether we want to use loops or not.

We can also return a promise from an async function, so we can write:

(async () => {  
  const arr = ['foo', 'bar', 'a', 'b'];  
  for await (let a of arr) {  
    console.log(a);  
    await sleep(2000);  
  }  
  return sleep(2000);  
})();

to return the sleep(2000) promise.

Also, we can give it a name and use it in other async functions as follows:

const foo = async () => {  
  const arr = ['foo', 'bar', 'a', 'b'];  
  for await (let a of arr) {  
    console.log(a);  
    await sleep(2000);  
  }  
  return sleep(2000);  
};

(async () => {  
  await foo();  
  console.log('c');  
})();

This shows that async functions are promises.

Conclusion

In JavaScript, there’s no sleep function like in other languages. However, we can make our own easily.

With promises, we can solve timing issues easily. It makes time-delayed code execution clean and readable. We can write time-delayed JavaScript code by using the setTimeout function.

The async and await syntax makes reading and writing the code a breeze.

Finally, we can call async functions in other async functions since these types of functions return promises only.

Categories
JavaScript JavaScript Basics

What’s so Special About JavaScript Functions?

In JavaScript, there are multiple ways to declare a function. One way is to declare it with the function keyword. The other way is to declare it as an arrow function.

In fact, there are two ways to declare a function with the function keyword. One way is using function declarations, which are also called function statements, and the other is to use function expressions.

In JavaScript, functions are first-class, which means that they’re objects we can define on the fly.


Function Declarations

Function declarations, also called function statements, are the way we define a function — with the function keyword followed by the name of the function.

For example, we can write the following to define a function with a function declaration:

function foo(){  
  return 'foo';  
}

A function declaration is stored in memory prior to executing the program. This means we can reference it anywhere in our code, even before it’s declared. Storing a variable in memory prior to executing the program is called “hoisting” in JavaScript.

For example, if we write the following:

console.log(foo());

function foo() {  
  return 'foo'  
}

console.log(foo());

We get foo logged from both function calls.


Function Expressions

Function expressions are functions stored as a value of a variable.

For example, to define a function as a function expression, we write:

const foo = function() {  
  return 'foo'  
}

Unless they’re function declarations or statements, function expressions aren’t stored in memory before the program runs. The function is defined in run-time, so we can only reference them after they’re declared.

For example, if write the follwing:

console.log(foo());

const foo = function() {  
  return 'foo'  
}

console.log(foo());

We’ll get the following error: Uncaught ReferenceError: Cannot access ‘foo’ before initialization’.

In the code above, we have the variable declaration when the program initially runs, but we don’t have the function assigned to it yet, so we can’t access it. Also, anything defined with the let , or const keywords can’t be used with those variables or constants before it’s defined, which also prevents it from being run.


When Should We Use Function Declarations or Expressions?

It depends on personal style. Function declarations are more convenient — they’re available in any part of the script — while function expressions let us assign a function to a variable and reference the variable in various ways, like the calling methods it has.

First-Class Functions

As we see in the function expression example, we can assign a function to a variable in JavaScript. The term for this is a first-class function. First-class functions are functions defined on the fly as the program runs.

This is because in JavaScript, functions are objects just like everything else. Functions have their own methods and other properties and can be used just like objects.

For example, all functions have the toString method to convert them to a string with the code that defines the function.

Other methods in a function would be methods that call a function with a different this value, like bind , call , and apply.

We can use the toString method by writing the following code:

function foo() {  
  return 'foo'  
}

console.log(foo.toString());

Then we get the following from the console.log:

function foo() {  
  return 'foo'  
}

The bind, call, and apply methods are similar. They all take an object for the this keyword in the function as the first argument. bind and call take a comma-separated list of arguments for the other arguments and apply takes an array of arguments as the second argument.

For example, we can change the value of this in a function with the call method by writing the following code:

let obj = {  
  firstName: 'Joe',  
  lastName: 'Smith'  
}

let person  = {  
  firstName: 'Jane',  
  lastName: 'Smith',  
  getFullName()  {  
    return `${this.firstName} ${this.lastName}`  
  }  
}

console.log(person.getFullName());  
console.log(person.getFullName.call(obj));

The first example would be the same except that we change call to apply, since we didn’t pass in the second or subsequent arguments:

let obj = {  
  firstName: 'Joe',  
  lastName: 'Smith'  
}

let person  = {  
  firstName: 'Jane',  
  lastName: 'Smith',  
  getFullName()  {  
    return `${this.firstName} ${this.lastName}`  
  }  
}

console.log(person.getFullName());  
console.log(person.getFullName.apply(obj));

Then we get Jane Smith for the first console.log, since we haven’t changed the value with apply yet, but we changed the value of this to obj with the apply method in the second console.log so that we get Joe Smith.

We can call bind with an object passed in, as in the following code:

let person = {  
  firstName: 'Jane',  
  lastName: 'Smith',  
  getName() {  
    return `${this.firstName} ${this.lastName}`  
  }  
}

const joe = {  
  firstName: 'Joe',  
  lastName: 'Smith'  
}

console.log(person.getName.bind(joe)());

Then we get 'Joe Smith' since we passed in the joe object into the first argument of the bind method, which sets the this object inside the getName method to the joe object.

In JavaScript, there are two ways to declare a function with the function keyword. One way is using function declarations, which are also called function statements, and the other is to use function expressions.

Function declarations are defining a function with the function keyword followed by the name of the function. They are available anywhere in the program.

Function expressions are functions assigned to variables. They’re only available after they’re declared and assigned to the variable.

In JavaScript, functions are first-class, which means that they’re objects that we can define on the fly.

With these features in mind, we can use in ways that are different from languages like Java, where functions can only be inside classes.

Categories
JavaScript

What are Rxjs Subscriptions?

A Subscription in RxJS is a disposable resource that usually represents the execution of an Observable. It has the unsubscribe method which lets us dispose of the resource held by the subscription when we’re done.

It’s also called ‘Disposable’ in earlier versions of RxJS.

Basic Usage

A basic example of a subscription can be seen in the following code:

import { of } from "rxjs";
const observable = of(1, 2, 3);  
const subscription = observable.subscribe(val => console.log(val));  
subscription.unsubscribe();

In the code above, the subscription returned when we call subscribe on an Observable is a subscription. It has the unsubscribe method, which we called on the last line to clean up when the Observable is unsubscribed.

Combining Subscriptions

We can combine subscriptions with the add method that comes with Subscription objects.

For example, if we have 2 Observables:

import { of } from "rxjs";
const observable1 = of(1, 2, 3);  
const observable2 = of(4, 5, 6);
const subscription1 = observable1.subscribe(val => console.log(val));
const subscription2 = observable2.subscribe(val => console.log(val));
subscription1.add(subscription2);

In the code above, we have 2 Subscriptions, subscription1 and subscription2, which we joined together with the add method of subscription1.

subscription1 is a parent of subscription2.

We should get

1  
2  
3  
4  
5  
6

as the output.

When we join Subscriptions together, we can unsubscribe to all the Subscriptions that were joined together by calling unsubscribe on the first Subscription that the add method is called on.

For example, if we have:

import { interval } from "rxjs";
const observable1 = interval(400);  
const observable2 = interval(300);
const subscription = observable1.subscribe(x => console.log(x));  
const childSubscription = observable2.subscribe(x => console.log(x));
subscription.add(childSubscription);

Then calling unsubscribe on subscription will unsubscribe from all the subscriptions that are joined together.

setTimeout(() => {  
  subscription.unsubscribe();  
}, 1000);

Undoing Child Subscriptions

We can undo child subscriptions by using the Subscription’s remove method. It takes a child Subscription as the argument.

To use it, we can write something like the following code:

import { interval } from "rxjs";

const observable1 = interval(400);  
const observable2 = interval(300);
const subscription = observable1.subscribe(x => console.log(x));  
const childSubscription = observable2.subscribe(x => console.log(x));

subscription.add(childSubscription);

(async () => {  
  await new Promise(resolve => {  
    setTimeout(() => {  
      subscription.remove(childSubscription);  
      resolve();  
    }, 600);  
  }); 

  await new Promise(resolve => {  
    setTimeout(() => {  
      subscription.unsubscribe();  
      childSubscription.unsubscribe();  
      resolve();  
    }, 1200);  
  });  
})();

Once the childSubscription is removed, it’s no longer a child of the subscription Subscription.

Therefore, we’ve to call unsubscribe on both subscriptions separately so that we clean up both subscriptions once we’re done.

Subscriptions let us get the values emitted from an Observable. We can join multiple Subscriptions together with the add method, which takes a child Subscription as its argument.

When they’re joined together, we can unsubscribe to them together.

We can remove a Subscription as a child of another Subscription with the remove method.

Categories
JavaScript JavaScript Basics

What are Higher-Order Functions in JavaScript?

In JavaScript, higher-order functions are used in many places. Therefore, it’s important to know what they are.

In this article, we’ll look at what higher-order functions are and how to use them in JavaScript.

Definition of Higher-Order Functions

Higher-order functions are functions that take other functions as arguments or return functions as their results. A function that’s accepted as an argument is also called a callback function.

Why can functions accept other functions as arguments or return functions? This is because JavaScript functions are objects like any other entity in JavaScript. Functions that are objects are called first-class functions.

First-class functions are treated like any other variables. In JavaScript, this is the case, so JavaScript functions are first-class functions.

In JavaScript, we can assign functions to variables:

let foo = () => 1;

In the code above, we assigned a simple anonymous function to the foo variable.

Then we can call it by running:

foo();

We can also add properties to it as follows:

foo.bar = 1;

The code above is bad practice because it’s confusing since functions are usually called rather than manipulated by adding properties to them.

However, we know from this that JavaScript functions are objects. It also has a prototype with methods like apply, bind, and call to modify the behavior of regular functions declared with the function keyword.

Everything that we want to do with other variables like numbers, strings, and objects, we can do with functions.

Functions as Function Parameters

Because JavaScript functions are just regular objects, we can pass them in as arguments when we call a function. This is used in many places like array functions and promise callbacks.

A simple example would be the following:

const addOrMultiply = (addFn, multiplyFn, a, b) => {  
  if (Math.random() > 0.5) {  
    return addFn(a, b);  
  }  
  return multiplyFn(a, b);  
}

const add = (a, b) => a + b;  
const multiply = (a, b) => a * b;  
const result = addOrMultiply(add, multiply, 1, 2);

In the code above, we defined the addOrMultiply function which takes a function to add 2 numbers, function to multiply 2 numbers, and 2 numbers as arguments.

In the function, if Math.random() returns a number bigger than 0.5, then we call addFn(a, b) . Otherwise, we call multiplyFn(a, b) .

Then we defined the add and multiply functions to add and multiply 2 numbers respectively.

Finally, we call the addOrMultiply function by passing inadd and multiply functions and numbers 1 and 2.

This way, the functions we pass in get called with a and b . This doesn’t mean that the function we pass in have to match the signature of the function calls inside the addOrMultiply function. JavaScript doesn’t care about the signatures of the function we pass in. However, we’ve to pass in functions that get us the expected results.

By the definition that we mentioned for higher-order function, addOrMultiply fits the definition of it.

Examples of Higher-Order Functions

Array.prototype.forEach

We can use the forEach method to loop through each element of an array. It takes a callback function as an argument. The callback takes the array entry currently being processed, index of the array being processed, and the array itself as the parameter.

The index and the array parameters are optional. However, we know that JavaScript doesn’t care about the function signature of functions we use for callbacks, so we’ve to be careful.

We can write the following code:

const arr = [1, 2, 3];  
arr.forEach((a, i) => console.log(`arr[${i}] is ${a}`))

We should see:

arr[0] is 1  
arr[1] is 2  
arr[2] is 3

logged from the console.log .

Array.prototype.map

The map array method takes the same callback function as forEach . It’s used for mapping array entries of the array it’s called on to values returned by manipulating each entry with the callback function. It returns a new array.

For example, we can use is as follows:

const arr = [1, 2, 3];  
arr.map((a, i) => a**2)

Then we should get:

[1, 4, 9]

setTimeout

The setTimeout function delays the execution of the code inside the callback function that we pass into it by a specified amount of time.

For example, we can use it as follows:

setTimeout(() => {  
  console.log('hi');  
}, 1000)

The code above will log 'hi' 1 second after the setTimeout function is called.

setTimeout defers the code inside the callback to the next event loop iteration so that we delay the execution of the code in the callback without holding up the whole program.

This kind of delayed code is asynchronous. We delay code execution without holding up the main execution thread to wait for its execution to finish.

This pattern is common to lots of asynchronous code, including callbacks for promises, event listeners and other pieces of asynchronous code.

Since we can’t execute asynchronous code line by line, callbacks are even more important since it’s the only way to run a function in an indeterminate amount of time.

Event Handlers

Event handlers for DOM elements and in Node.js also use callbacks since there’s code that is only called when an event is triggered.

For example, we can attach a simple click listener to the document object as follows:

document.addEventListener('click', () => {  
  console.log('clicked');  
})

Then whenever we click on the page, we’ll get 'clicked' logged.

As we can see higher-order functions are very useful in JavaScript. It lets us create callback functions to pass into other functions. It’s widely used by synchronous code and asynchronous code alike.

Synchronous callbacks examples include callbacks that we pass into array methods.

Asynchronous callbacks include event handlers, setTimeout , promise callbacks and more. It’s widely used with asynchronous code since the code isn’t run line by line, so we need callbacks to run code that needs to be run in an indeterminate amount of time.

Categories
JavaScript

Using Rxjs Join Creation Operators to Combine Observer Data

RxJS is a library for reactive programming. Creation operators are useful for generating data from various data sources to be subscribed to by Observers.

In this article, we’ll look at some join creation operators to combine data from multiple Observables into one Observable. We’ll look at the combineLatest, concat, and forkJoin operators.

combineLatest

We can use the combineLatest to combine multiple Observables into one with values that are calculated from the latest values of each of its input Observables.

It takes 2 or more Observables as arguments or one array of Observable as an argument. It returns an Observable that emits values that are an array of values of all the Observables that were passed in.

combineLatest also takes an optional project function, which takes an argument of all values that would be normally be emitted by the resulting Observable, then we can return what we want given the values in that function.

combineLatest works by subscribing to each Observablke in order and whenever an Observable emits, collect the emitted data into an array of the most recent values of each Observable. Then the array of values gets emitted by the returned Observable.

To ensure that the output array always has the same length, combineLastest wait for all input Observables to emit at least once before it starts emitting results. If some Observable emits values before others do, then those values will be lost.

If some Obsetrvables doesn’t emit by completes, then the returned Observable will complete without emitting anything since that one didn’t emit any value.

If at least one Observable was passed into combineLatest and all of them emitted something, then the returned Observable will complete when all the combined streams complete. In this case, the value will always be the last emitted value for the Observables that completed earlier.

For example, we can use it as follows:

import { combineLatest, of } from "rxjs";
const observable1 = of(1, 2, 3);  
const observable2 = of(4, 5, 6);  
const combined = combineLatest(observable1, observable2);  
combined.subscribe(value => console.log(value));

Then we get:

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

since observable1 emitted all its values before observable2 did.

We can also use the optional second argument to do some calculations:

import { combineLatest, of } from "rxjs";  
import { map } from "rxjs/operators";
const observable1 = of(1, 2, 3);  
const observable2 = of(4, 5, 6);  
const combined = combineLatest(observable1, observable2).pipe(  
  map(([a, b]) => a + b)  
);  
combined.subscribe(value => console.log(value));

In the code above, we got the sum of the values. Then we get:

7  
8  
9

These are the sum of each entry that we have before.

concat

We can use the concat operator to take multiple Observables and return a new Observable that sequentially emits values from each Observable that were passed in.

It works by subscribing to them one at a time and merging the results in the output Observable. We can pass in an array of Observables or put them directly as arguments. Passing in an empty array will result in an Observable that completes immediately.

concat doesn’t affect Observables in any way. When an Observable completes, it’ll subscribe to the next one an emit its values. This will be repeated until the operator runs out of Observables.

merge operator would output values from Observables concurrently.

If some input Observable never completes, concat will also never complete and Observables follows them will never be subscribed. If some Observable completes without emitting any values, then it’ll be invisible to concat .

If any Observable in the chain emit errors, then the error will error immediately. Observable that would be subscribed after the one that errors will never be subscribed to.

We can pass in the same Observable subscribe to the same one repeatedly.

For example, we can use it as follows:

import { concat, of } from "rxjs";
const observable1 = of(1, 2, 3);  
const observable2 = of(4, 5, 6);  
const concatted = concat(observable1, observable2);  
concatted.subscribe(value => console.log(value));

Then we get:

1  
2  
3  
4  
5  
6

as we expect.

forkJoin

forkJoin accepts an array of Observables and emits an array of values in the exact same order as the passed array or a dictionary of values in the same shape as the passed dictionary.

The returned Observable will emit the last values emitted of each Observable. For example, we can write:

import { forkJoin, of } from "rxjs";
const observable1 = of(1, 2, 3);  
const observable2 = of(4, 5, 6);  
const joined = forkJoin(observable1, observable2);  
joined.subscribe(value => console.log(value));

Then we get [3, 6] .

We can also pass in an object with Observables as properties:

import { forkJoin, of } from "rxjs";
const observable1 = of(1, 2, 3);  
const observable2 = of(4, 5, 6);  
const joined = forkJoin({ observable1, observable2 });  
joined.subscribe(value => console.log(value));

Then we get:

{observable1: 3, observable2: 6}

Conclusion

The combineLatest, concat, and forkJoin operators are very useful for combining emitted data from multiple Observables.

With combineLatest, we can combine emitted data from multiple Observables and get arrays of values that are formed by the latest values emitted by each Observable that we passed in.

The concat operator subscribes to each Observable that we passed in sequentially and return an Observable that emits values from each sequentially. If an error occurs in any Observable, an error will be emitted by the returned Observable.

Finally, the forkJoin operator returns an Observable that get the latest values from each Observable and emits the value as an object or an array depending if you passed in a dictionary of Observables or an array of Observables.