---
title: Bitovi Academy - Promises
description: Learn about JavaScript promises
---

- ![AI implementation](https://www.bitovi.com/hubfs/AIConsultingIcon.svg)
  
  [AI implementation](https://www.bitovi.com/services/ai-consulting?hsLang=en-us)
- ![Systems engineering](https://www.bitovi.com/hubfs/icon%20-%20backend.svg)
  
  [Systems engineering](https://www.bitovi.com/services/systems-engineering-consulting?hsLang=en-us)
- ![Project management](https://www.bitovi.com/hubfs/icon%20-%20PM.svg)
  
  [Project management](https://www.bitovi.com/services/agile-project-management-consulting?hsLang=en-us)
- ![Product design](https://www.bitovi.com/hubfs/icon%20-%20design.svg)
  
  [Product design](https://www.bitovi.com/services/product-design-consulting?hsLang=en-us)
- ![Frontend development](https://www.bitovi.com/hubfs/icon%20-%20frontend.svg)
  
  [Frontend development](https://www.bitovi.com/services/frontend-development-consulting?hsLang=en-us)
- [View more
  
  →
  
  ](https://www.bitovi.com/digital-consulting-services?hsLang=en-us)

We're Experts in...

- [JavaScript](https://www.bitovi.com/services/frontend/javascript-consulting?hsLang=en-us)
- [AI training](https://www.bitovi.com/ai-training-for-software-engineers?hsLang=en-us)
- [Angular](https://www.bitovi.com/services/frontend/angular-consulting?hsLang=en-us)
- [Design Systems](https://www.bitovi.com/services/axure-figma-migration?hsLang=en-us)
- [React](https://www.bitovi.com/services/frontend/react-consulting?hsLang=en-us)
- [Temporal](https://www.bitovi.com/services/backend/temporal-consulting?hsLang=en-us)
- [React Native](https://www.bitovi.com/services/frontend/react-consulting/react-native?hsLang=en-us)
- [Node.js](https://www.bitovi.com/services/backend/nodejs-consulting-1?hsLang=en-us)

Showcase

![Yum! Brands](https://www.bitovi.com/hubfs/yum-showcase-link-1.png)

[View case study](https://www.bitovi.com/en/bitovi-yum-case-study?hsLang=en-us)

More Projects

- [![Levi's](https://www.bitovi.com/hubfs/levis.svg)](https://www.bitovi.com/web-application-consulting-work/levis-ecommerce-responsive-redesign?hsLang=en-us)
- [![Christie's International Real Estate](https://www.bitovi.com/hubfs/christies.svg)](https://design.bitovi.com/christies)
- [![BAFS](https://www.bitovi.com/hubfs/bafs.svg)](https://www.bitovi.com/ux-design-consulting/ux-case-studies/bafs-ppp?hsLang=en-us)
- [View more
  
  →
  
  ](https://www.bitovi.com/our-software-consulting-work?hsLang=en-us)

Open Source Tools

We build powerful tools and open source them to support the community.

[See what we've built →](https://www.bitovi.com/open-source?hsLang=en-us)

- [![Blog](https://www.bitovi.com/hubfs/icon%20-%20blog.svg)
  
  BlogWe post about perfecting software delivery
  
  ](https://bitovi.com/blog)
- [![Partnerships](https://www.bitovi.com/hubfs/Handshake-1.svg)
  
  PartnershipsLearn about Bitovi's technology partners
  
  ](https://www.bitovi.com/partnerships?hsLang=en-us)
- [![Academy](https://www.bitovi.com/hubfs/limbo/icons/icon-academy.svg)
  
  AcademyFree courses to build delivery skills
  
  ](https://www.bitovi.com/academy/?hsLang=en-us)
- [![Open source tools](https://www.bitovi.com/hubfs/icon%20-%20open%20source.svg)
  
  Open source toolsUse our tools or contribute to our open source mission.
  
  ](https://www.bitovi.com/open-source?hsLang=en-us)

Let's Connect

- [![Discord](https://www.bitovi.com/hubfs/DiscordLogo.svg)
  
  Discord
  
  ](https://discord.gg/J7ejFsZnJ4)
- [![LinkedIn](https://www.bitovi.com/hubfs/LinkedinLogo.svg)
  
  LinkedIn
  
  ](https://www.linkedin.com/company/bitovi/)
- [![GitHub](https://www.bitovi.com/hubfs/GithubLogo.svg)
  
  GitHub
  
  ](https://github.com/bitovi/)

![Eggbot](https://www.bitovi.com/hubfs/build_assets/bitovi-limbo-cms-react/338/js_client_assets/assets/eggbot-LTGhdSGL.png)

Name *

Work Email *

Phone

What's your project?

Send

### Contact Us

(312) 620-0386contact@bitovi.com

- [ Advanced JavaScript ](https://www.bitovi.com/academy/learn-advanced-javascript.html?hsLang=en-us) 
    - [ JavaScript and the DOM ](https://www.bitovi.com/academy/learn-advanced-javascript/js-vs-dom.html?hsLang=en-us)
    - [ Types, Operators and Primitives ](https://www.bitovi.com/academy/learn-advanced-javascript/js-types.html?hsLang=en-us)
    - [ Comparison Operators ](https://www.bitovi.com/academy/learn-advanced-javascript/js-comparison.html?hsLang=en-us)
    - [ Closures ](https://www.bitovi.com/academy/learn-advanced-javascript/closures.html?hsLang=en-us)
    - [ Context ](https://www.bitovi.com/academy/learn-advanced-javascript/context.html?hsLang=en-us)
    - [ Prototypes ](https://www.bitovi.com/academy/learn-advanced-javascript/prototypes.html?hsLang=en-us)
    - [ Classes ](https://www.bitovi.com/academy/learn-advanced-javascript/classes.html?hsLang=en-us)
    - [ Promises ](https://www.bitovi.com/academy/learn-advanced-javascript/promises.html?hsLang=en-us)
- [ DOM and jQuery ](https://www.bitovi.com/academy/learn-dom-jquery.html?hsLang=en-us)
- [ Debug JavaScript ](https://www.bitovi.com/academy/learn-to-debug-javascript.html?hsLang=en-us)
- [ Learn TypeScript ](https://www.bitovi.com/academy/learn-typescript.html?hsLang=en-us)
- [ Learn React Native ](https://www.bitovi.com/academy/learn-react-native.html?hsLang=en-us)
- [ Learn Web Components ](https://www.bitovi.com/academy/learn-web-components.html?hsLang=en-us)
- [ Agile Program Management With Jira ](https://www.bitovi.com/academy/learn-agile-program-management-with-jira.html?hsLang=en-us)
- [ Learn RxJS ](https://www.bitovi.com/academy/learn-rxjs.html?hsLang=en-us)
- [ Giving a Training ](https://www.bitovi.com/academy/training.html?hsLang=en-us)
- [ Learn Technology Consulting ](https://www.bitovi.com/academy/learn-technology-consulting.html?hsLang=en-us)
- [ Learn React ](https://www.bitovi.com/academy/learn-react.html?hsLang=en-us)
- [ Learn NgRx ](https://www.bitovi.com/academy/learn-ngrx.html?hsLang=en-us)
- [ Learn Graphql ](https://www.bitovi.com/academy/learn-graphql.html?hsLang=en-us)
- [ Learn Docker ](https://www.bitovi.com/academy/learn-docker.html?hsLang=en-us)
- [ Learn CanJS ](https://www.bitovi.com/academy/learn-canjs.html?hsLang=en-us)
- [ Learn Angular ](https://www.bitovi.com/academy/learn-angular.html?hsLang=en-us)
- [ Advanced TypeScript ](https://www.bitovi.com/academy/advanced-typescript.html?hsLang=en-us)

[View More Courses](https://www.bitovi.com/academy/#courses) [ ]

# Promises `page`

Learn about JavaScript promises

> **NOTE:** This section is currently under development. There are no exercises yet.

## What is a promise

A promise represents the completion or failure of some operation. Promises have methods (`.then`) that let you listen for when the operation completes:

```
const myPromise = operationThatCompletesInTheFuture();

myPromise.then( function success(){
  console.log( "operation completed 😄" );
} );
```

You can also listen to when an operation fails:

```
const myPromise = operationThatCompletesInTheFuture();

myPromise.catch( function failure(){
  console.log( "operation failed 😟" );
} )
```

For example, you might use [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) to make a request and want to know if a connection was established:

```
const request = fetch("https://dog.ceo/api/breeds/list/all");

request.then( function fulfilled(){
  console.log( "connection established" );
});

request.catch( function rejected(){
  console.log( "connection failed" );
} )
```

## Success values

If the operation is successful, the operation can return a value. For example, if `fetch` establishes a value, a `response` object is provided.

```
const request = fetch("https://dog.ceo/api/breeds/list/all");

request.then( function(response){
  console.log(response.status) // Logs 200
});
```

Setting a promise’s returning value is actually called *resolving* the promise’s value. This is because a promise’s value can only be set once.

## Failure reasons

If the operation fails, a reason for the failure can be returned. For example, if `fetch` makes a request to a URL that doesn’t exist, the `reason` will be an TypeError object.

```
const request = fetch("http://foo.bar");

request.catch( function(reason){
  console.log(`The request failed with message: ${reason.message}`) /// TypeError: Failed to Fetch
});
```

When a promise fails, it is called *rejecting* the promise.

## Creating promises

You can create your own promises with `new Promise()`! The following example creates a promise whose value is resolved to a random number after one second. We also listen to when the value is resolved with `then` and log a message.

```
const numberPromise = new Promise( function( resolve ){
  setTimeout( function(){
    resolve( Math.random() );    // Sets the value of the promise
  },  1000 );
})

numberPromise.then( function( number ){
  console.log("number "+ number); // Logs "number 0.###"
} );
```

Notice:

- `new Promise( executor )` takes an `executor` function that is called with a `resolve` callback. `resolve` is used to set the value of the  
   promise.
- `.then( onFulfilled )` takes an `onFulfilled` function that is called when the promise is resolved. `onFulfilled` is called with the promise’s resolved value.

Example Implementation

The following implements a simplified version of promises. It does not handle errors, or calling handlers at the end of the current run loop.

```
class MyPromise {
  constructor( executor ) {
    this._fulfilledHandlers = [];
    this._state = "pending";

    const resolve = (value) => {
      this._value = value;
      this._fulfill();
    }

    executor( resolve );
  }
  then(onFulfilled) {
    this._fulfilledHandlers.push(onFulfilled);

    if(this._state === "resolved") {
      this._fulfill();
    }
  }
  _fulfill(){
    this._state = "resolved";

    const handlers = this._fulfilledHandlers;
    this._fulfilledHandlers = [];
    handlers.forEach( handler => handler(this._value) );
  }
}

const groupNamePromise = new MyPromise( function( resolve ){
  setTimeout( function(){
    resolve("Bitovi");    // Sets the value of the promise
  },  1000 );
})

groupNamePromise.then( function( groupName ){
  console.log("groupName", groupName); // Logs "groupName Bitovi"
} );
```

You can also create promises that can be rejected.

The following creates a random number every 100ms. If a number is greater than `0.9`, it will resolve with that number. If 10 numbers are created that are all less than `0.9`, the promise will be rejected.

```
const numberPromise = new Promise( function( resolve, reject ){
  let count = 0;

  const interval = setInterval( ()=> {
    count++;
    let number = Math.random();
    if( number > 0.9 ) {
      clearInterval( interval );
      resolve( number );
    }
    if( count >= 10) {
      clearInterval( interval );
      reject( new Error("Unable to find a number greater than 0.9") );
    }
  },100);
})

numberPromise.then( function( number ){
  console.log("number"+ number);
} );

numberPromise.catch( function( error ){
  console.error(error);
} );
```

### Shorthands

You can also create resolved and rejected promises with shorthands:

```
const numberPromise = Promise.resolve(123);

numberPromise.then(console.log) //-> 123
```

```
const numberPromise = Promise.reject( new Error("Borked") );

numberPromise.catch(console.log) //-> Error[Borked]
```

## Creating promises from other promises

One of the most common uses of promises is to take a promise value and convert it to another promise value.

A promise’s `.then( onFulfilled )` method always returns another *outer* promise. That *outer* promise will take on the value of what the `onFulfilled` function returns.

In the following example, notice how `breedsPromise` resolves to an object of breeds. However, the `toCount` function is returning the number of breeds. This return value is used to make `countPromise`. `countPromise` resolves to the total number of breeds.

```
const request = fetch("https://dog.ceo/api/breeds/list/all");

const breedsPromise = request.then( function( response ){
  console.log( "response", response )      //-> Response{status, body}
  return response.json();
});

const countPromise = breedsPromise.then( function toCount(breeds) {
  console.log("breeds", breeds);           //-> {message: {beagle,chow}}
  return Object.keys( breeds.message ).length;
});

countPromise.then( (count) => {
  console.log("count", count);             //-> 91
})
```

### Flattening promises

If a `onFulfilled` function returns another promise, the *outer* promise actually takes on the behavior of the returned promise. This was used in the above example. `response.json()` returns a promise, so `breedsPromise` took on the behavior of the result of `response.json()`.

> NOTE: The process of reducing nested observables into a single observable is often called flattening. This is what it’s called in RxJS's [mergeAll](https://rxjs-dev.firebaseapp.com/api/operators/mergeAll).

The following shows using a `delay()` function to delay when `countPromise` completes by 3 seconds. `delay` returns a promise that resolves after 3 seconds.

```
function delay(value){
  return new Promise( (resolve) => {
    setTimeout( function(){
      resolve(value);
    }, 3000);
  });
}

const request = fetch("https://dog.ceo/api/breeds/list/all");

const breedsPromise = request.then( response => response.json() );

let startTime;

const countPromise = breedsPromise.then( function toCount(breeds) {
  startTime = new Date();
  return delay( Object.keys( breeds.message ).length );
});

countPromise.then( (count) => {
  console.log("delay", new Date() - startTime ); // Logs 3000
  console.log("count", count);             
})
```

### Throwing exceptions

If an `onFulfilled` function throws an exception, this will reject the *outer* promise returned by `.then`.

For example, if `toCount` mistakenly read `breeds.data` instead of `breeds.message`, `countPromise` would be rejected:

```
const request = fetch("https://dog.ceo/api/breeds/list/all");

const breedsPromise = request.then( function( response ){
  console.log( "response", response )      //-> Response{status, body}
  return response.json();
});

const countPromise = breedsPromise.then( function toCount(breeds) {
  console.log("breeds", breeds);           //-> {message: {beagle,chow}}
  return Object.keys( breeds.data ).length;
});

countPromise.then( (count) => {
  console.log("count", count);
})
countPromise.catch( (reason) => {
  console.error(reason) //-> TypeError[Cannot convert undefined or null to object]
})
```

## Promise providers

Promises are returned by many APIs such as:

- The `fetch()` API returns a promise when a connection is established. You can also easily get a promise when the JSON response is complete:
  
  ```
  const myJSON = fetch("/my-data.json")
    .then( (response) => response.toJSON() )
  ```
- [getUserMedia](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia)
- [ServiceWorkerContainer.register(...)](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register)

## Promise syntax

JavaScript even has **special syntax** for using promises:

- [async](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) / [await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await) let you read the value of promises without calling `.then`.

```
async function getBreedsCount(){
  const response = await fetch("https://dog.ceo/api/breeds/list/all");

  const breeds = await response.json();

  return Object.keys( breeds.message ).length;
}

const countPromise = getBreedsCount();

countPromise.then( (count) => {
  console.log("count", count);             //-> 91
});
```

- [for await(of)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of) allows you to loop through an iterator that emits promises:
  
  ```
  const response = await fetch(url);
  for await (const chunk of response.body.getReader() ) {
  
    responseSize += chunk.length;
  }
  ```

## Timing

Promises' callback handlers are run in the `microtask queue` which is called at the end of the JavaScript event loop. This means a few things.

First, callbacks of resolved promises are *not* called immediately. Instead they are called at the end of the current event loop.

The following:

- sets a timeout callback for `1ms`
- runs code that should last longer than `20ms`
- sets a fulfilled promise callback

```
const promise = Promise.resolve();

setTimeout( ()=> {
  console.log("timeout callback");
},1);

var total = 0
for(var i = 0; i < 100000; i++) {
  total +=  Math.sqrt(i) * (i % 2 === 0 ? 1 : -1)
}

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

// Logs:
// "promise fulfilled"
// "timeout callback"
```

Second, this also means that `resolving` a promise does not call all callbacks immediately as shown in the following example:

```
let resolve;
const promise = new Promise( (pResolve)=> {
  resolve = pResolve;
} )

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

console.log("before resolve");
resolve();
console.log("after resolve");

// Logs:
// "before resolve"
// "after resolve"
// "promise fulfilled"
```

Why was this done? Consistency. As developers, you know that your callbacks will always be called sometime in the future. If callbacks were called immediately, this would have to be handled.

## Chaining vs callbacks

Without Promises, the common way of handling asynchronous behavior was to pass a success and failure callback to functions as follows.

```
doSomething( (filesData) => {
  processFiles(filesData.files, function(processedFilesData) => {
    writeHTML(processedFilesData.writableFiles, function() {
      console.log("completed!");
    }, failureCallback);
  }, failureCallback);
}, failureCallback);
```

This is hard to read and results in the classic callback pyramid of doom 🔥🔥🔥!

Fortunately, promises make this better, by making a much more linear process:

```
getFiles()
  .then( (filesData) => {
    return processFiles(filesData.files);
  })
  .then( (processedFilesData) => {
    return writeHTML(processedFilesData.writableFiles);
  }).
  then( ()=> {
    console.log("completed!")
  })
  .catch( failureCallback );
```

## Promise queues

Often, you want to run a series of tasks, but those tasks might be optional. Making this work with promises can be tricky.

```
let promise = getFiles();

if(options.debug) {
  promise = promise.then(printFiles)
}

promise = processFiles();

if(options.debug) {
  promise = promise.then(printProcessWarnings)
}

promise = promise.then(writeHTML);
```

One way to simplify this is to use a promiseQueue that wires up functions to be called one after another.

```
function promiseQueue(functions){
  var promise = functions.shift()();

  var func;
  while( functions.length ) {
    func = functions.shift();
    if(func) {
      promise = promise.then(func);
    }
  }
  return promise;
};

const promise = promiseQueue([
  getFiles,
  options.debug && printFiles,
  processFiles,
  options.debug && printProcessWarnings,
  writeHTML
]);
```

## Waiting for multiple async tasks to complete

Often, you might want to do two or more parallel tasks and then do something with the result. [Promise.all](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) takes multiple promises and returns another promise when they all complete.

For example, you might want to compare the number of `hound` to `dingo` breed images.

One way of doing that would be to get hounds and get dings and compare:

```
const time = new Date();

fetch("https://dog.ceo/api/breed/hound/images")

  .then( response=> response.json() )

  .then( (hounds) => {
    return fetch("https://dog.ceo/api/breed/dingo/images")
      .then( response => response.json() )
      .then( dingos => { return {hounds, dingos} })
  } )

  .then( ({hounds, dingos}) => {
    return {houndsCount: hounds.message.length, dingosCount: dingos.message.length}
  })

  .then( ({houndsCount, dingosCount}) => {
    console.log(`${houndsCount} hounds, ${dingosCount} dingos,
      time ${new Date() - time}`);
  } );
```

But this would create one request after another. Slow.

Instead, use `Promise.all()` to make both requests at the same time:

```
const time = new Date();

const houndsPromise = fetch("https://dog.ceo/api/breed/hound/images")
  .then( response=> response.json() );

const dingosPromise = fetch("https://dog.ceo/api/breed/dingo/images")
  .then( response => response.json() )

Promise.all([houndsPromise, dingosPromise])
  .then( ([hounds, dingos])=> {
    return {houndsCount: hounds.message.length, dingosCount: dingos.message.length}
  })
  .then( ({houndsCount, dingosCount}) => {
    console.log(`${houndsCount} hounds, ${dingosCount} dingos,
      time ${new Date() - time}`);
  } );
```

## Promises compared to alternatives

### Promises compared to callbacks

Callback functions can be passed to a function. In the following example, `doSomething()` takes a completion callback:

```
doSomething(someArg, function onComplete(err, data) {
  if(err) {
    // handle error case
  } else {
    // handle success
  }
});
```

This form of continuation passing is very common in Node.js.

**Callback positives:**

- Callbacks are lighter than promises - a function just needs to be created. Dispatching is also faster - a function just needs to be called.

**Callback negatives:**

- Callbacks only allow a single listener.
- Callbacks might be called immediately, which can create timing issues.
- Callbacks can create the *pyramid of doom*.

**When to use callbacks instead of promises**

If you are making something that needs to run extremely quickly and doesn’t need to be user friendly, callbacks might be a good solution. After all, it’s not difficult to "promisify" callback-based APIs. Many libraries do exactly this.

### Promises compared to event streams

Event streams are any technology that might produce values overtime. For example, listening to a `click` event on the DOM is a form of event stream:

```
document.body.addEventListener("click", (event) => {
  console.log("Got a click event", event);
})
```

[RxJS](https://www.bitovi.com/academy/learn-rxjs.html?hsLang=en-us) is a functional-reactive event stream library. The following uses RxJS to create an event stream (`subject`) that emits two random numbers:

```
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.2.1/rxjs.umd.js"></script>
<script type="typescript">
const {Subject} = rxjs;

const subject = new Subject<number>();

subject.subscribe({
  next: (v) => console.log(`observerA: ${v}`)
});

subject.next(Math.random());
subject.next(Math.random());
subject.complete();
</script>
```

Modern browsers even provide their own stream primitive - `ReadableStream`. This lets you create a stream of events.

**Event stream positives:**

- Event streams can emit values over time. Promise can not do this.
- Event streams can be cancelled. There’s no way to do this through the promise API.
- Event streams often have utility libraries, making deriving new event streams from other event streams easy.

**Event stream negatives:**

- You must stop listening to an event stream or end the stream to avoid memory leaks.
- Event streams are often heavier than Promises.
- With the exception of `ReadableStream` (which isn’t in every environment yet), streams are not part of the JavaScript specification and are not present in every environment. Promises come for free for almost every user.

**When to use streams instead of promises**

If your system produces a single "event", returning a promise is generally better than returning an event stream. Most event stream libraries have ways of converting a promise to an event stream.

However, if your system produces multiple events, you have no choice but to use some form of event stream.

###### On this page...

###### Get help

If you need [help](https://discord.gg/J7ejFsZnJ4) with an exercise, please reach out to us on [Discord](https://discord.gg/J7ejFsZnJ4)

If you find a bug, please [create an issue](https://github.com/bitovi/academy/issues/new) or email [contact@bitovi.com](mailto:contact@bitovi.com?Subject=Training%20Suggestion)

## Join the Bitovi Newsletter

 Do you want to receive updates about new Bitovi Academy courses, Bitovi open source projects, and dev community news? If so, please provide your email. We won’t spam you or give it away for any reason!  
*By providing your email you agree to receive communications from Bitovi*

![](https://bitovi.github.io/academy/static/img/close.svg)

```json
{
     "@context": "http://schema.org",
     "@type": "Organization",
     "mainEntityOfPage":{
          "@type":"WebPage",
          "@id":"https://www.bitovi.com/academy/learn-advanced-javascript/promises.html",
          "description": "Learn about JavaScript promises 
"
     },
     "url": "http://bitovi.com",
     "logo": "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg",
     "image": "https://www.bitovi.com/hubfs/bitovi-logo-x2.png",
     "name": "Bitovi Web App Consulting",
     "alternateName": "Bitovi",
      "naics": "541511",
      "description": "Bitovi is a UX, UI design and front-end JavaScript development consulting company",
     "address": {
          "@type": "PostalAddress",
          "streetAddress": "1134 Pine Tree Lane ",
          "addressLocality": "Libertyville",
          "addressRegion": "IL",
          "addressCountry": "United States",
          "postalCode": "60048"
     },
     "areaServed": {
          "@type": "GeoCircle",
          "geoMidpoint": {
               "@type": "GeoCoordinates",
               "latitude": "41.8781",
               "longitude": "87.6298"
          },
          "geoRadius": "5000 km"
     },
     "telephone": "312-620-0386",
     "email": "contact@bitovi.com",
     "sameAs": [
          "https://www.facebook.com/BitoviLLC/",
          "https://twitter.com/bitovi",
          "https://www.linkedin.com/company/bitovi"
     ]
}
```