24
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PromiseとAwaitの違い、Promiseで勘違いしたこと

Last updated at Posted at 2020-07-06

「PromiseとAwaitの違い」というタイトルがもう、わかってない感がすごくてヤバイっすね
Promiseが基礎機能で、Awaitはpromiseを使って待つ仕組み的なもの。

Promise の .then() は待たないという話

Promise の .then() は一気に実行される。最初のとこすら待ってくれない。一気に流したいなら promise 作って then するだけで非同期になる。 .then() の中でAPI取得とかしてたら、(実行順は揃うけど結果の)前後はまったく保証されない。

e.g.

4秒待つ、3秒待つ、2秒待つ・・・と時間がかかるかと思いきや、最期の1秒待つやつから順に帰ってくる。

log = (str) => console.log(str);

new Promise(function(resolve, reject) {
  setTimeout(() => log(4000), 4000);
  resolve();
}).then((result) => {
  setTimeout(() => log(3000), 3000);
}).then((result) => {
  setTimeout(() => log(2000), 2000);
}).then((result) => {
  setTimeout(() => log(1000), 1000);
});

result

1000
2000
3000
4000

待つために Await がある

先の例を順番通り実行したい場合は、awaitで同期モードにする。

worker = (i) => {
	return new Promise((resolve) => {
		setTimeout(function(){resolve(i)}, i);	
	});
}

async function start() {
	let res = await worker(4000);
	log(res);
	res = await worker(3000);
	log(res);
	res = await worker(2000);
	log(res);
	res = await worker(1000);
	log(res);
}

start();

result

4000
3000
2000
1000

await に then() をぶら下げても、一気に実行される

最初の4000にだけawaitをつける
→ 4000はすぐ実行される
→ その他は4000の直後にだららっと実行される(非同期モード)

worker = (i) => {
	const promise = new Promise((resolve) => {
		setTimeout(function(){
			console.log(i);
			resolve(i);
		}, i);	
	});
	return promise;
}

async function start() {
	let res = await worker(4000)
				.then(worker(3000))
				.then(worker(2000))
				.then(worker(1000));
}

start();

result

000
2000
3000
4000

意味不明すぎるので、狙ってたとしてもこんなことはしてはいけない。(これがやりたい場合は素直に Promise.all() しましょう)

then() の中でawait すれば、待つ

then() の中でも async を書かないといけないので少しトリッキー。


worker = (i) => {
	const promise = new Promise((resolve) => {
		setTimeout(function(){
			console.log(i);
			resolve(i);
		}, i);	
	});
	return promise;
}

async function start() {
	let res = await worker(4000)
				.then(async () => await worker(3000))
				.then(async () => await worker(2000))
				.then(async () => await worker(1000))
}

start();

result

4000
3000
2000
1000

結論

awaitはawaitだけで使う。then()とは組み合わせない (チェーンにしない)

// good 
await worker(1);
await worker(2);

// wrong
await worker(1)
      .then(async () => await worker(2))

追記 ->
await同士を組み合わせて待ちたい場合の記事を書いた
https://qiita.com/uturned0/items/74ff00cbef3290d0aed2
<-

以上、基礎連でした。

アロー関数ちなみに

アロー関数のことをラムダ式と呼ぶらしい。

これは

log = (str) => console.log(str);

これと同じ

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

1行だけなら {} が省略できる

引数が1つなら () すら省略できる

log = str => console.log(str);

log = str が並んでる時点でかなりヤバイ見た目になる。

24
16
1

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
24
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?