async/await の await後にevent.preventDefault()されないのはなぜですか?
質問内容
<label><input type="checkbox" id="c1" value="on">チェックボックス1</label>
$('#c1').get(0).checked = false;
$('#c1').on('click', async function(e) {
let clickElement = this;
let checked = clickElement.checked;
console.log(`checked: ${checked}`);
//=> true
let promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
let message = '3秒後です';
console.log(message);
resolve(message);
}, 3000);
});
e.preventDefault(); // ← awaitの前で行うとe.preventDefault()される。
await promise1
.then(() => {
console.log('非同期処理成功');
//clickElement.checked = checked;
})
.catch(() => {
console.log('非同期処理失敗');
//clickElement.checked = !checked;
});
// e.preventDefault(); // ← awaitの後で行うとe.preventDefault()されない。
console.log('click end');
});
チェックボックスのclickイベントハンドラで非同期処理を実行させているのですが、e.preventDefault()
をawait promise1
の前で実行すると preventDefault()された上で非同期処理をawaitしてくれます。
今回質問したい内容は、タイトルにも書いているのですが e.preventDefault()
をawait promise1
の後で実行すると preventDefault()の処理が正常に動かないのです。
動かないという事実はコードを書いて理解したのですが、どういった理由でそのような挙動になるのかご存知の方はいないでしょうか?
自分が把握していること
event.preventDefault()
- ブラウザのデフォルト動作をキャンセル(防ぐ)処理のこと。
- event.preventDefault()が実際に動作するのは、イベントハンドラの処理が終了した後に動く。
- チェックボックスのブラウザデフォルト動作はチェック状態を切り替えるということ。 checkbox の preventDefault
stackoverflowでの参考になりそうな回答
javascript - event.preventDefault in async functions - Stack Overflow
Yes, it is totally possible to call preventDefault() in an async event handler function. You only have to ensure to make the call before the first await, as otherwise the event already will have happened when the function resumes. The event flow will continue and not wait for the promise that the event handler returns.
この回答によれば、awaitで待機する前にpreventDefault()を処理しておかないと、ブラウザのデフォルト動作がすでに動いてしまうらしいです。
非同期処理はawaitで待機されるけど、イベントハンドラー(click)の処理は待機されず awaitと書いた時点で終了扱いとなる?