Skip to content

Promises

Pierre Cauchois edited this page May 15, 2017 · 1 revision

Using the Azure IoT Hub SDK for Node.js with Promises

Promises provide a more elegant way to write asynchronous code, but are not supported by all versions of the Node.js runtime (not without external libraries at least). For this reason, we have so far limited the use of promises in our SDK, and instead opted for more traditional callback-based APIs.

This being said, if your code is already using promises and would benefit from consistency, there are simple ways to "wrap" existing API into Promises.

Using Bluebird

The library bluebird provides a Promise implementation that is compatible with a large number of versions of Node.js and can automate wrapping the APIs of the SDK. Since all APIs follow the "nodeback" convention, "promisification" of the SDK can be achieved easily using the promisifyAll function on any top-level object of the SDK, for example:

var Registry = require('azure-iothub').Registry;
var bluebird = require('bluebird');

var connectionString = process.env.IOTHUB_CONNECTION_STRING;
var registry = bluebird.promisifyAll(Registry.fromConnectionString(connectionString));

registry.listAsync()
        .then((deviceList) => console.log(JSON.stringify(deviceList)))
        .catch((err) => console.log(err.toString()));

Using Typescript or ES6

When running on a more recent version of node (6 and higher) you can also rely on the built-in support of promises instead of having to use a separate library, by wrapping the callbacks yourself:

import {
    Device,
    Registry
} from 'azure-iothub';

const connectionString = process.env.IOTHUB_CONNECTION_STRING;
const registry = Registry.fromConnectionString(connectionString);

/**
 * Get list of Devices in IoT Registry - returns Promise
 */
const listDevices = (registry: Registry): Promise<Device[]> => {
  return new Promise<Device[]>((resolve, reject) => {
    registry.list((error: Error, deviceList: Device[]) => {
      if (error) {
        reject(error);
      } else {
        resolve(deviceList);
      }
    });
  });
};

listDevices(registry)
  .then((deviceList) => console.log(JSON.stringify(deviceList)))
  .catch((err) => console.log(err.toString()));

Using async/await

this was suggested by @peterblazejewicz in #38. Thanks!!

In the latest versions of ES6 and Typescript, the async and await keywords have been added and allow an even more fluid way of writing code. Using the same example as before:

import {
    Device,
    Registry
} from 'azure-iothub';

const connectionString = process.env.IOTHUB_CONNECTION_STRING;
const registry = Registry.fromConnectionString(connectionString);

/**
 * Get list of Devices in IoT Registry - returns Promise
 */
const listDevices = async (registry: Registry): Promise<Device[]> => {
  return new Promise<Device[]>((resolve, reject) => {
    registry.list((error: Error, deviceList: Device[]) => {
      if (error) {
        reject(error);
      } else {
        resolve(deviceList);
      }
    });
  });
};
(async() => {
  try {
    const deviceList: Device[] = await listDevices(registry);
    console.log(JSON.stringify(deviceList));
  } catch (error) {
    console.log(error);
  }
})();