#
ドキュメント

Document

自分のための備忘録です。

Promise・async/await

Ref

let promise = new Promise(function(resolve, reject) {
// executor (生成コード, "シンガー")
});

new Promise へ渡される関数は executor(執行者) と呼ばれます。new promise が作成されると、executor は自動的に実行されます。それは最終的に結果を生成コードを含んでいます。上記の例の言葉では、executor は “シンガー” です。

ref. https://ja.javascript.info/promise-basics

Promise

基本

https://jsfiddle.net/ で確認。 DevToolsのConsoleではうまく確認できません。

// https://ja.javascript.info/promise-basics
function createPromise() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if ((Math.random()) > 0.5) {
                resolve('RESOLVE!!')
            }
            reject('REJECT!!')
        }, 1000);
    });
}

const promise = createPromise();
promise
    .then(
        // 第一引数のコールバックはresolveによって呼び出される
        (value) => {
            console.log(value);
        },
        // 第2引数はのコールバックはrejectによって呼び出される
        (value) => {
            console.log(value)
        });

以下は上記の糖衣構文。

function createPromise() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if ((Math.random()) > 0.5) {
                resolve('RESOLVE!!')
            }
            reject('REJECT!!')
        }, 1000);
    });
}

const promise = createPromise();
promise
    .then(
        // 第一引数のコールバックはresolve
        (value) => {
            console.log(value);
        }
    )
    // thenの第2引数の代わりにrejectをcatchで受ける
    // catchは必ずしもErrorオブジェクトではない(例ではString)
    .catch((err) => { console.log(err) });

catchの例2。Errorオブジェクトをcatchで捕捉する。

function createPromise() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if ((Math.random()) > 0.5) {
                resolve('RESOLVE!!')
            }
            reject(new Error('Error occurs'))
        }, 1000);
    });
}

const promise = createPromise();
promise
    .then(
        // 第一引数のコールバックはresolve
        (value) => {
            console.log(value);
        }
    )
    // thenの第2引数の代わりにrejectをcatchで受ける
    // catchは必ずしもErrorではない
    .catch((err) => { console.log(err.message) });

コールバックが実行されるタイミング

Promiseはインスタンスを生成した時点でコンストラクタへ渡したコールバックが実行される。

/*
 * Promiseはインスタンスを生成した時点で
 * コンストラクタへ渡したコールバックが実行される
 *
 * コメント数字は実行順序
 * promise.thenが3, 4より遅く(非同期に)実行される理由は下記のリンクを参照
 * https://azu.github.io/promises-book/#promise-is-always-async
 */
const promise = new Promise(resolve => {
  console.log('first.');        // ----- (1)
  resolve('done.');
});

console.log('something 1.');    // ----- (2)

/*
 * thenは非同期に実行
 */
promise.then((data) => {
  console.log(data)            // ----- (5)
});

console.log('something 2.')    // ----- (3)
console.log('something 3.')    // ----- (4)

// first.
// something 1.
// something 2.
// something 3.
// done.

Promiseチェーン

/*
 * Promiseの例
 * 直列処理で1秒間隔で2回日付を表示し最後にcompleteを出力
 */
function showFirstTime() {
  return new Promise(resolve => {
    setTimeout(() => {
        resolve('First Time: ' + new Date().toString());
      },
      1000);
  });
}

function showSecondTime() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('Second Time: ' + new Date().toString());
    }, 1000);
  });
}

// ここから実行
showFirstTime()
  .then((value) => {
    console.log(value);
    return showSecondTime();
  })
  .then((value) => {
    console.log(value);
    console.log('complete');
  });

// First Time: Sat Dec 17 2022 15:55:32 GMT+0900 (日本標準時)
// Second Time: Sat Dec 17 2022 15:55:33 GMT+0900 (日本標準時)
// complete

Async/Await

基本

  • await f()の戻り値はresolveされた値
  • await f()でf()がrejectされた場合は例外が発生(try catch)で処理
    • 上記より awaitはresolveは戻り値、rejectはtry catchで処理
/*
 * awaitはasyncの中で使用できる
 * const result = await f(); のresultはresolveされた値を取得する
 *
 */
function createPromise() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if ((Math.random()) > 0.5) {
                resolve('RESOLVE!!')
            }
            reject('REJECT!!')
        }, 1000);
    });
}

async function sample() {
    /*
     * await promiseはresolveの場合は値を返す
    * rejectの場合はエラーをスローするのでcatchで上取れる(例ではerrは文字列 REJECT!! になる
    */
    
    try {
    const result = await createPromise();
    console.log(result)
    } catch(err) {
        console.log(err)
    }
}

sample();

サンプル

async自体は非同期

function createPromise() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if ((Math.random()) > 0.5) {
        resolve('RESOLVE!!')
      }
      reject('REJECT!!')
    }, 1000);
  });
}

/*
 * async自体は同期的ではない
 * 後述のconsole.log('Something.')が先に実行される
 */
(async () => {
  /*
   * await promiseはresolveの場合は値を返す
   * rejectの場合はエラーをスローするのでcatchで受け取れる(例ではerrは文字列 REJECT!! になる
   */
  try {
    const result = await createPromise();
    console.log(result)
  } catch (err) {
    console.log(err)
  }
})();

console.log('Something.');

await

/*
 * async/await
 * https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/async_function
 * TypeScriptではエラー バージョンの問題か
 */

function resolveAfter1Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 1000);
  });
}

async function add1(x) {
  var a = resolveAfter1Seconds(20);
  var b = resolveAfter1Seconds(30);
  return x + await a + await b;
}

add1(10).then(v => {
  console.log(v); // prints **60** after 1 seconds.
});

async function add2(x) {
  var a = await resolveAfter1Seconds(20);
  var b = await resolveAfter1Seconds(30);
  return x + a + b;
}

add2(10).then(v => {
  console.log(v); // prints **70** after 2 seconds.
});

日付表示

/*
 * Async/Await
 * 直列処理で1秒間隔で2回日付を表示
 *
 * 別サンプルで下記も参照
 * https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/async_function
 */
function nowTime() {
  return new Promise(resolve => {
    window.setTimeout(() => {
        console.log("Time: " + new Date().toString());
        resolve();
      },
      1000);
  });
}

async function showTime() {
  await nowTime();
  await nowTime();
}

// ここから実行
showTime();

サンプル

function createTimer() {
    return new Promise( (resolve, reject) => {
        setTimeout( () => resolve( 'aaa' ), 3000 )
    } );
}

async function sync() {
    const response = await createTimer();
    console.log(response);
    return 'bbb'
}

sync().then((value) => {
    console.log(value);
})

console.log('zzz');

// zzz
// aaa
// bbb
// ==UserScript==
// @name         Esa link replace
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://h-sawai.docbase.io/posts/*/edit
// @icon         https://www.google.com/s2/favicons?domain=docbase.io
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    let objectToString = Object.prototype.toString;

    const wait = (sec) => {
        return new Promise((resolve, reject) => {
            const intervalId = setInterval(()=> {
                const element = document.querySelector('.CodeMirror-codey');
                if (element !== null) {
                    clearInterval(intervalId);
                    resolve(element);
                }
            }, sec*1000);
      });
    };

    async function main() {
        try {
            const codearea = await wait(1);
            console.log(codearea.innerHTML);
        } catch (err) {
            console.error(err);
        }
    }
     main();
})();