LoginSignup
1
2

More than 1 year has passed since last update.

Promiseとasync/awaitについて解説

Last updated at Posted at 2022-08-04

はじめに

JSを久々に書くとPromiseを忘れてしまうため、見返せるように記事にしてみました。

Promiseとは

Promise オブジェクトは、非同期処理の完了 (もしくは失敗) の結果およびその結果の値を表します。

Promiseオブジェクト生成

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('foo');
  }, 300);
});

Promiseを返す関数を生成

function test(time) {
	// Promiseを返す
	return new Promise(
		(resolve ,reject) => {
			setTimeout(() => {
				resolve('foo');
			}, time);
		}
	);
}
// Promiseオブジェクトを作成
const myPromise = test(300);

Promiseの連鎖

Promiseにはpromise.then(), promise.catch(), promise.finally()の各メソッドが存在する。
これらは promise を返すため、メソッドチェーンとして使うことができる。

function checkMail() {
	return new Promise((resolve, reject) => {
        // 50%の確率で成功
		if (Math.random() >= 0.5) {
    		resolve('Mail has arrived');
    	} else {
    		reject(new Error('Failed to arrive'));
    	}
	});
}

checkMail()
	.then((mail) => {
		console.log(mail);
	})
	.catch((err) => {
		console.error(err);
	})
	.finally(() => {
		console.log('Experiment completed');
	});

promise.then()

then() メソッドは Promise を返します。最大 2 つの引数として、
Promise が成功した場合失敗した場合コールバック関数を取ります。

promise.catch()

catch() メソッドは Promise を返しますが、失敗した場合のみ扱います。
then(undefined, onRejected) の呼び出しと同じ動作です。
簡潔に言うと例外を投げたり、rejectを返すときに使う。

promise.finally()

finally() メソッドは Promise を返します。
Promiseが確立したら、成功か失敗かにかかわらず、指定されたコールバック関数が実行されます。

静的メソッド

Promise.all()

複数のPromiseオブジェクトをまとめて処理します。
全てのPromiseが成功するか、失敗するまで待ちます。

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
    console.log(values);
    // 出力結果: Array [3, 42, "foo"]
});

Promise.resolve()

Promise.resolve() メソッドは、与えられた値で成功した Promise オブジェクトを返します。

静的な Promise.resolve メソッドの使用
Promise.resolve('Success').then(function(value) {
    console.log(value); // "Success"
}, function(value) {
    // 呼び出されない
});

Promise.reject()

Promise.reject() メソッドは、引数で与えられた理由で失敗した Promise オブジェクトを返します。

function resolved(result) {
    console.log('Resolved');
}

function rejected(result) {
    console.error(result);
}

Promise.reject(new Error('fail')).then(resolved, rejected);
// 出力結果: Error: fail

async/awaitとは

async および await を使用することで、
Promiseベースの非同期の動作を、Promiseチェーンを明示的に構成する必要なく
よりすっきりとした方法で書くことができます。
又、非同期コードに通常の try/catch ブロックを使用することができます。

書き方の違い

下記のPromise関数を then/catchasync/await で処理の違いをみる。

function test1() {
	return new Promise(resolve => {
		setTimeout(() => {
			resolve('resolved1');
		}, 2000);
	});
}

function test2() {
	return new Promise(resolve => {
		setTimeout(() => {
			resolve('resolved2');
		}, 3000);
	});
}

then/catchのケース

test1()test2()が入れ子になり、ネストが深くなっている。

// 1回目
test1()
	.then((result) => {
		console.log(result);
		// 2回目
		test2()
			.then((result2) => {
				console.log(result2);
			}).catch((e) => {
				console.log(e);
			});
	}).catch((e) => {
		console.log(e);
	});

async/awaitのケース

ネストが浅くなり、見やすくなった。

(async () => {
	try {
		// 1回目
		const result = await test1();
		console.log(result);
		// 2回目
		const result2 = await test2();
		console.log(result2);
    } catch (e) {
		console.log(e)
    }
})()

おまけ

コールバック関数

resolverejectで呼ぶ

function test(resolve , reject) {
	if (Math.random() >= 0.5) {
		resolve('Success');
	} else {
		reject('Error');
	}
}
function result(value){ console.log(value); }
function error(value){ console.log(value); }

new Promise(test).then(result, error);

promiseオブジェクトを引数へ

function callfunc(fn) {
	const maybePromise = fn();
	// Promiseのみ許可
	if (maybePromise instanceof Promise) {
		return maybePromise.finally(() => {
			console.log('Suceess');
		})
	} else {
		console.log('Error')
	}
}

callfunc(async () => {
	try {
		console.log('start');
	} catch (e) {
		console.log(e);
	}
});

さいごに

以上です。
Promiseの静的メソッドは他にもあり、使い方もそれぞれ存在するため
改めて確認が必要だなと思いました。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2