ニフクラ mobile backend(mBaaS)お役立ちブログ

スマホアプリ開発にニフクラ mobile backend(mBaaS)。アプリ開発に役立つ情報をおとどけ!

Node.jsのスクリプトがasync/awaitに対応しました

f:id:mbaasdevrel:20171212211252p:plain

Node.jsのスクリプトがasync/awaitに対応しました

先日、スクリプト機能がバージョンアップしてNode.jsが8.11.3を選択できるようになりました。この8系以降の特徴として、async/awaitに対応したという点があります。async/awaitはJavaScriptの非同期処理を同期処理のように書ける記法になります。コールバックやPromiseで苦しんだ経験のある方はぜひasync/awaitを使ってみてください。

コードの例

例えばNode.js 6系の場合は以下のようなコードになります。

var NCMB = require('ncmb');
module.exports = function(req, res) {
  var application_key = 'd28...fc0';
  var client_key      = 'f94...1cc';

  var ncmb = new NCMB(application_key, client_key);
  var Item = ncmb.DataStore('Item');
  var item = new Item(req.body.item);
  item.save()
    .then(function(obj) {
      return res.status(201).json(obj);
    })
    .catch(function(err) {
      return res.status(503).json(err);
    });
};

これを Node.js 8系の書き方に直します。

const NCMB = require('ncmb');
module.exports = async (req, res) => {
  const application_key = 'd28...fc0';
  const client_key      = 'f94...1cc';

  const ncmb = new NCMB(application_key, client_key);
  const Item = ncmb.DataStore('Item');
  const item = new Item(req.body.item);
  try {
    await item.save()
    res.status(201).json(obj);
  } catch (err) {
    res.status(503).json(err);
  }
};

いかがでしょう。結果を返す部分まで含めるとインデントが一段減ったのが分かるかと思います。その分コードの見通しが良くなります。

複数のPromise処理による変数の引き継ぎが解消

async/awaitを使った時の最大のメリットはPromise処理を複数つないだ時の変数の引き継ぎが容易になるということです。例えば以下のような処理を考えてみます。前に処理したデータを新しいデータに紐付けつつ保存すると言った処理です。

var NCMB = require('ncmb');
module.exports = function(req, res) {
  var application_key = 'd28...fc0';
  var client_key      = 'f94...1cc';

  var ncmb = new NCMB(application_key, client_key);
  var Item = ncmb.DataStore('Item');
  var item = new Item(req.body.item);
  item.save()
    .then(function(obj) {
      var item2 = new Item();
      item2.set('item', obj);
      return item2.save();
    })
    .then(function(obj) => {
      var item3 = new Item();
      item3.set('item', obj);
      return item3.save();
    })
    .then(function(obj) => {
      // item2にアクセスできない
    })
    .catch(function(err) {
      return res.status(503).json(err);
    });
};

このようにPromiseを繰り返すと、その間にある変数へのアクセスが困難になります。そのため、Promiseの範囲内にグローバル変数を定義して、上書きしたりします。

var NCMB = require('ncmb');
module.exports = function(req, res) {
  var application_key = 'd28...fc0';
  var client_key      = 'f94...1cc';

  var ncmb = new NCMB(application_key, client_key);
  var Item = ncmb.DataStore('Item');
  var item = new Item(req.body.item);
  var globalItem = null;
  item.save()
    .then(function(obj) {
      var item2 = new Item();
      item2.set('item', obj);
      return item2.save();
    })
    .then(function(obj) => {
      globalItem = obj;      // これを追加
      var item3 = new Item();
      item3.set('item', obj);
      return item3.save();
    })
    .then(function(obj) => {
      // globalItemでアクセス
    })
    .catch(function(err) {
      return res.status(503).json(err);
    });
};

しかし、複数の変数を対象とした場合に毎回追加していくのは面倒です。これはPromiseの場合、簡単に解決できます。多段で実行されるPromiseが分かりやすくなります。

const NCMB = require('ncmb');
module.exports = async (req, res) => {
  const application_key = 'd28...fc0';
  const client_key      = 'f94...1cc';

  const ncmb = new NCMB(application_key, client_key);
  const Item = ncmb.DataStore('Item');
  const item = new Item(req.body.item);
  try {
    await item.save()
    // 次のItem
    item2 = new Item();
    item2.set('item', item);
    await item2.save();
    
    // 次のItem
    item3 = new Item();
    item3.set('item', item2);
    await item3.save();
    
    // item2でアクセスできる
  } catch (err) {
    return res.status(503).json(err);
  }
};

まとめ

Webブラウザでもasync/awaitがサポートされるようになっていますが、レガシーなWebブラウザも対象にした場合は使いづらいでしょう。しかしスクリプト機能であればNode.jsのバージョンが固定なので、安心してasync/awaitが利用できます。ネットワーク処理をはじめ、非同期処理を簡単に書けるようになりますので、ぜひasync/awaitを使っていきましょう。

スクリプト : 各言語で利用可能なバージョン | ニフクラ mobile backend

中津川 篤司

中津川 篤司

NCMBエヴァンジェリスト。プログラマ、エンジニアとしていくつかの企業で働き、28歳のときに独立。 2004年、まだ情報が少なかったオープンソースソフトの技術ブログ「MOONGIFT」を開設し、毎日情報を発信している。2013年に法人化、ビジネスとエンジニアを結ぶDXエージェンシー「DevRel」活動をスタート。