Help us understand the problem. What is going on with this article?

ECMAScript6のアロー関数とPromiseまとめ - JavaScript

More than 3 years have passed since last update.

はじめに

この記事ではアロー関数とpromiseについての、使い方のまとめです。とくにpromiseに関しては、非同期処理の鉄板、async.jsとの比較をしながらその実装方法を見ていきます。

そのまえに、ECMAScript6の基本構文はこちら。
ECMAScript6の基本構文まとめ - JavaScript

技術情報のみつぶやくアカウント作成しました。ECMAScript6などの最新情報も追っていきます。
Twitter: @takeharumikami

RSSはこちら
Feedly: Feedlyをフォロー
RSS: http://qiita.com/takeharu/feed

アロー関数

アロー関数の記述の仕方

アロー関数では、従来の無名関数より簡潔に記述できます。

  • Before
var show = function(text) {
  console.log(text);
};
  • After

1.「function」記法を「=>」記法へ

// アロー関数
var show = (text) => {
  console.log(text);
};

2.引数が一つの時には()を省略可能

var show = text => {
  console.log(text);
};

3.さらに一文の場合は、{}とreturnの省略も可能。

var show = (text) => text + ' さようなら';

var text = show('こんにちは');
console.log(text); // こんにちは さようなら

thisを束縛する

まずthisの挙動では、JavaScript初学者は必ずといっていいほど悩まされます。
今までだと、bindでthisを束縛したり、thisを別名の変数に退避する方法などがありました。一般的には後者の退避がよくつかわれます。_this, self, thatなどといった変数名にするのが通例となっています。
ECMAScript6からはアロー関数を用いることにより、thisを束縛し、予想通りの挙動を得ることができます。

thisの挙動についてはこちら
JavaScriptの「this」は「4種類」??

  • Before
var counter = {
  count: 0,

  start: function() {
    // thisを別名で退避
    var self = this;

    setTimeout(function() {
      // ここでのthisはcounterではないため、退避した変数selfを使用する
      self.count++;
    }, 1000);
  }
};
  • After
var counter = {
  count: 0,

  start: function() {
    setTimeout(() => {
      this.count++
    }, 1000);
  }
};

非同期処理を処理する、Promise(async.jsとの比較)

こちらでは、非同期処理の鉄板、async.jsとの比較をしながらその実装方法を見ていきます。

async.jsの基本的な使い方はこちら
JavaScriptのasync.jsでwaterfallとseries、parallelの違い

Promise.resolveメソッドによる順次処理の実行(async.jsのwaterfall)

  • asycn.waterfall

async.jsのwaterfallとの比較です。

async.waterfall([
  function(callback) {
    console.log('1');
    setTimeout(function() {
      console.log('1 done');
      callback(null, 1);
    }, 100);
  },

  function(value, callback) { // value === 1
    console.log('2');
    setTimeout(function() {
      console.log('2 done');
      callback(null, 2);
    }, 50);
  },

  function(value, callback) { // value === 2
    console.log('3');
    setTimeout(function() {
      console.log('3 done');
      callback(null, 3);
    }, 10);
  }
], function(err, value) { // value === 3
  if (err) {
    return console.log(err);
  }
  console.log('all done.');
});

//出力結果
1
1 done
2
2 done
3
3 done
all done.
  • Promise.resolveメソッドによる順次処理

Promise.resolveメソッドでは、thenによるメソッドチェーンにより、直感的にわかりやすく、順次処理を実現できます。resolveの引数に後続の処理へと値を渡すことができます。

Promise.resolve()
.then(function() {
  return new Promise(function(resolve, reject) {
    console.log('1');
    setTimeout(function() {
      console.log('1 done');
      resolve(1);
    }, 100);
  })
})
.then(function(value) { // value === 1
  return new Promise(function(resolve, reject) {
    console.log('2');
    setTimeout(function() {
      console.log('2 done');
      resolve(2);
    }, 50);
  });
})
.then(function(value) { // value === 2
  return new Promise(function(resolve, reject) {
    console.log('3');
    setTimeout(function() {
      console.log('3 done');
      resolve(3);
    }, 10);
  });
})
.then(function(value) { // value === 3
  console.log('all done');
})
.catch(function(err) {
  console.log(err);
})
;

//出力結果
1
1 done
2
2 done
3
3 done
all done.

Promise.allメソッドによる非同期処理の複数同時実行(async.jsのparallel)

  • async.parallel

async.jsのparallelとの比較です。

async.parallel([
  function(callback) {
    console.log('1');
    setTimeout(function() {
      console.log('1 done');
      callback(null, 1);
    }, 100);
  },

  function(callback) {
    console.log('2');
    setTimeout(function() {
      console.log('2 done');
      callback(null, 2);
    }, 50);
  },

  function(callback) {
    console.log('3');
    setTimeout(function() {
      console.log('3 done');
      callback(null, 3);
    }, 10);
  }
], function(err, results) {
  if (err) { 
    return console.log(err);
  }
  console.log('all done');
  console.log(results);
});

//出力結果
1
2
3
3 done
2 done
1 done
all done
[1, 2, 3] 
  • Promise.all

Promise.allメソッドでは、配列でPromiseオブジェクトを渡すことにより、それらの処理を非同期で並列に処理することが可能となります。

Promise.all([
  new Promise(function(resolve, reject) {
    console.log('1');
    setTimeout(function() {
      console.log('1 done');
      resolve(1);
    }, 100);
  }),

  new Promise(function(resolve, reject) {
    console.log('2');
    setTimeout(function() {
      console.log('2 done');
      resolve(2);
    }, 50);
  }),

  new Promise(function(resolve, reject) {
    console.log('3');
    setTimeout(function() {
      console.log('3 done');
      resolve(3);
    }, 10);
  })
]).then(
  function(results) {
    console.log('all done');
    console.log(results);
  },

  function(err) {
    console.log(err);
  }
);

//出力結果
1
2
3
3 done
2 done
1 done
all done
[1, 2, 3] 

Promise.raceメソッド

上記のようにPromise.allメソッドはすべての処理が完了されてから、後続の処理が実行されます。それに対してPromise.raceメソッドは、一つでも処理が完了されるとその時点で後続の処理を実行します。

Promise.race([
  new Promise(function(resolve, reject) {
    console.log('1');
    setTimeout(function() {
      console.log('1 done');
      resolve(1);
    }, 100);
  }),

  new Promise(function(resolve, reject) {
    console.log('2');
    setTimeout(function() {
      console.log('2 done');
      resolve(2);
    }, 50);
  }),

  new Promise(function(resolve, reject) {
    console.log('3');
    setTimeout(function() {
      console.log('3 done');
      resolve(3);
    }, 10);
  })
]).then(
  function(results) {
    console.log('first done');
  },

  function(err) {
    console.log(err);
  }
);

//出力結果
1
2
3
3 done
first done
2 done
1 done

後編の記事

ECMAScript6の最後の記事ではクラスについてまとめます。

アカウント

技術情報のみつぶやくアカウント作成しました。ECMAScript6などの最新情報も追っていきます。
Twitter: @takeharumikami

RSSはこちら
Feedly: Feedlyをフォロー
RSS: http://qiita.com/takeharu/feed

おすすめの記事

ECMAScript6の基本構文はこちら。
もうはじめよう、ECMAScript6の基本構文まとめ - JavaScript

JavaScriptでは関数型言語の一部の機能?実践的なJavaScriptの関数型とは。
JavaScriptで関数型プログラミングの入門

良質なスタイルガイドを真似したいなら、GoogleやjQueryを参考に。
Javascriptのスタイルガイドまとめ(おすすめ4選)

takeharu
【名前】三上丈晴 【経歴】北海道大学理学院数学専攻を経て、2012年新卒入社。現在ピグパーティ プロダクトマネージャ 【著書】Git逆引き入門
https://twitter.com/takeharumikami
cyberagent
サイバーエージェントは「21世紀を代表する会社を創る」をビジョンに掲げ、インターネットテレビ局「AbemaTV」の運営や国内トップシェアを誇るインターネット広告事業を展開しています。インターネット産業の変化に合わせ新規事業を生み出しながら事業拡大を続けています。
http://www.cyberagent.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away