プログラミングマガジン

プログラミングを中心にIT技術をできるだけわかりやすくまとめます。

  • ホーム
  • JavaScript
  • 【JavaScript】非同期処理を簡単にし、コールバック地獄から脱出させる「Promis…
 
 
     
  • サーバー言語  
    • Python
    • Ruby
    • PHP
    • SQL
  •  
  • インフラ  
       
    • AWS
    •  
    • 基本
    • Git
  • Web
       
    • Web開発
    • JavaScript
    • Vue.js
    • React
  •  
  • 設計  
       
    • 実装設計
    • DB設計
  • 問い合わせ
  

【JavaScript】非同期処理を簡単にし、コールバック地獄から脱出させる「Promiseオブジェクト」について

07.07

  • miyabisan2
  • コメントを書く

この記事は3分で読めます

コールバック関数を利用すると、何度もコールバック関数が呼ばれて、ソースコードの入れ子構造が複雑になるという「コールバック地獄」という問題が発生してきました。

その問題を解決するのが、「ECMAScript2015」で採用されたPromiseオブジェクトというオブジェクトです。

Promiseオブジェクトの特徴

  • 非同期処理を監視するためのオブジェクトです。
  • 「ブラウザオブジェクト」ではなく、「JavaScript標準の組み込みオブジェクト」である。

Promiseオブジェクト使用の流れ

1.Promiseオブジェクトを返す関数を作る方法

非同期処理の対象となる関数でPromiseオブジェクトを返すように定義します。その際にPromiseクラスの中でコールバック関数(function(resoleve)〜)を定義するようにします。

1
2
3
4
5
6
7
function 関数(){
return new Promise(){
  //コールバック関数
  function(resolve){
  }
}.then(コールバック関数);
}

Promiseオブジェクトのコンストラクタは、下記2つの引数を取ります。

引数 説明
resolve 第一引数として取り、指定は、必須になります。処理結果が正常だった場合に、「then」によって設定した次の関数を呼びます。これもPromiseオブジェクトのメソッドになります。
reject 任意です。処理結果が異常だった場合に実行させます。

thenメソッド

resolveメソッドを読んだ際に、このthenで設定したメソッドが呼ばれます。resolveメソッドの第一引数が、次にthenで呼ぶメソッドの引数になります。

用途

順番に非同期処理を実行したいかつ、前の処理の処理結果を次の処理に使いたい場合に使えます。

実装例

1
2
3
4
5
6
7
8
9
10
11
function task1(){
return new Promise(function (resolve, reject) {
  console.log('test')
        //引数として渡された「task1」を次のthenメソッドのコールバック関数内の第一引数(result1)として渡す。
  resolve('task1');
}).then((result1) => {
  console.log(result1)
});
}
 
task1();

Promiseの中の処理結果をresolveによってthenに渡しています。逆にPromiseのコールバック関数の中にresolveメソッドを定義していない場合は次のthenを呼ぶ事ができないので例えresolveに渡す引数がなかったとしても必ずresolveメソッドを定義するようにしましょう。

2.関数同士をつなぐ方法(メソッドチェーン)

1
関数1.then(成功時に呼ぶ関数2,失敗時に呼ぶ関数2).then(成功時に呼ぶ関数3,);

普通のコールバック関数の入れ子に比べて非常に読みやすいですよね。

元々、jQueryや、AngularJSといったライブラリにはこのような機能が付属されていましたが、ECMAScript2015より、標準のJavaScriptでも利用できるようになったのです。

thenメソッド

Promiseオブジェクトでの結果を受けるメソッドです。

用途

いちいち、非同期処理用の関数を宣言しなくても、関数の中で非同期処理を呼べたりします。

実装例

1
2
3
4
5
6
new Promise(function(resolve){
console.log('test')
    resolve();
}).then(function(resolve){
console.log('test2')
})

実装例2

成功時の処理と、失敗時の処理で分岐させる例です。なお、Promiseクラス内のコールバック関数で次のthenの引数にする場合はresolveの第一引数に指定する仕様でしたが、thenメソッドからthenメソッドに引数を渡す場合はreturnで渡す事になるので注意です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
new Promise(function(resolve){
console.log('test')
    resolve('戻り値');
}).then(function(resolveからの引数){
console.log('成功時')
        return 戻り値;
},function(thenからの引数){
console.log('失敗時')
        return 戻り値;
}).then(function(thenからの引数){
console.log('成功時2')
},function(){
console.log('失敗時2')
})

実装例3

なお、thenのコールバック関数の中でPromiseオブジェクトを改めて返したとしても同じ挙動になります。

1
2
3
4
5
6
7
8
9
10
11
12
13
hidouki().then(text => {
  //  console.log("あ");
  console.log(text);
  return "かきくけこ"
}).then(text => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("たちつてと")
    }, 100)
  });
}).then(a => {
  console.log(a); //たちつてと
});

Promise.all

上記thenをつなげる例でも少し冗長に見える場合があります。さらにすっきりさせたい場合は下記のように記述します。最終的なコールバックの連続の結果はthenで受けます。

1
2
3
4
5
6
7
Promise.all([]
  コールバック関数1,
  コールバック関数2
])
//処理結果
.then((([引数]) =>{
});

catchメソッド

catchメソッドを使うとrejectを実行した結果を捕まえる事が可能です。

1
2
3
4
5
6
7
8
9
10
11
12
13
function hidouki() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("エラー発生");
    }, 100);
  });
}
hidouki().then(text => {
  console.log(text);
})
.catch(error => {
  console.log(error);
});

Exceptionでも呼ぶ事が可能

1
2
3
4
5
6
7
8
9
10
11
12
function hidouki() {
  return new Promise((resolve, reject) => {
    throw new Exception("エラー発生");
  });
}
hidouki().then(text => {
  console.log(text);
})
  .catch(error => {
    console.log(error);  //ReferenceError: Exception is not defined
    return "finallyに渡す";
  })

finally

catchの後にthenをつなげばJavaのtry 〜 catchでいうfinallyと同じ役割の処理を記述する事が可能です。catchメソッドのコールバック関数内でreturn文を使う事でfinallyに引数を渡す事が可能です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function hidouki() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("エラー発生");
    }, 100);
  });
}
hidouki().then(text => {
  console.log(text);
})
  .catch(error => {
    console.log(error);
    return "Finallyに渡す";
  }).then(text => {
    console.log("Finally");
    console.log(text);       //Finallyに渡す
  });

静的なresolveメソッド

下記のように単純にPromiseからthenに対して引数を渡すだけのメソッドを使う場合は静的メソッドのresolveメソッドを使うと楽です。

1
2
3
4
5
6
7
8
function hidouki() {
  return new Promise((resolve, reject) => {
    resolve("渡す");
  });
}
hidouki().then(text => {
  console.log(text);
})

Promiseオブジェクトの静的メソッドになるのでnewする必要はありません。

1
2
3
4
5
6
function hidouki() {
  return Promise.resolve("渡す");
};
hidouki().then(text => {
  console.log(text); //渡す
})

スポンサーリンク
  • 2018 07.07
  • miyabisan2
  • コメントを書く
  • JavaScript
  • Tweets Twitter
  • このエントリーをはてなブックマークに追加
  • LINEで送る

関連記事

  1. 2020 04.05

    【JavaScript】「CORS」、「クロスドメイン制約」とは?

  2. 2021 08.16

    【JavaScript】「TypeScript」でESlintを使うための設定

  3. 2018 07.07

    【JavaScript】「call/apply/bindメソッド」について

  4. 2022 10.10

    【Prisma】sqliteで実装

  5. 2021 08.16

    【JavaScript】「import」と「require」の違い

  6. 2018 04.11

    【jQuery】イベント処理について深く理解する。

  • コメント ( 0 )
  • トラックバック ( 0 )
  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

返信をキャンセルする。

【JavaScript】「Web Storage(スト…

【JavaScript】「関数リテラル(匿名関数)」、…

RETURN TOP

著者プロフィール

エンジニア歴10年で過去に業務系、Webデザイン、インフラ系なども経験あります。現在はWeb系でフロントエンド開発中心です。

詳細なプロフィールはこちら

スポンサーリンク

カテゴリー

  • Android
  • AngularJS
  • API
  • AWS
  • C++
  • CSS
  • cursor
  • C言語
  • DDD
  • DevOps
  • Django
  • Docker
  • Figma
  • Git
  • GitLab
  • GraphQL
  • gRPC
  • Hasura
  • Java
  • JavaScript
  • Kubernetes
  • Laravel
  • linux
  • MySQL
  • Next.js
  • nginx
  • Node.js
  • NoSQL
  • Nuxt.js
  • Oracle
  • PHP
  • Python
  • React
  • Redux
  • Rspec
  • Ruby
  • Ruby on Rails
  • Sass
  • Spring Framework
  • SQL
  • TypeScript
  • Unity
  • Vue.js
  • Webサービス開発
  • Webデザイン
  • Web技術
  • インフラ
  • オブジェクト指向
  • システム開発
  • セキュリティ
  • その他
  • データベース
  • デザインパターン
  • テスト
  • ネットワーク
  • プログラミング全般
  • マイクロサービス
  • マイクロソフト系技術
  • マルチメディア
  • リファクタリング
  • 副業
  • 未分類
  • 業務知識
  • 生成AI
  • 設計
  • 関数型言語
RETURN TOP

Copyright ©  プログラミングマガジン | プライバシーポリシー