サーチ…


構文

  • 新しいプロミス(/ *実行者関数:* /関数(解決、拒否){})
  • promise.then(onFulfilled [、onRejected])
  • promise.catch(onRejected)
  • Promise.resolve(解決策)
  • Promise.reject(理由)
  • Promise.all(iterable)
  • Promise.race(iterable)

備考

約束はECMAScript 2015仕様の一部であり、 ブラウザのサポートは限られており、2017年7月現在世界中のブラウザの88%がサポートしています。次の表は、約束をサポートする最も初期のブラウザのバージョンの概要を示しています。

クロムエッジ Firefox インターネットエクスプローラオペラ Opera Miniはサファリ iOS Safari
32 12 27 バツ 19 バツ 7.1 8

それらをサポートしていない環境では、 Promiseはポリフェイルすることができます。サードパーティのライブラリは、コールバック関数の自動化された「約束」や、 notifyなどのprogressなどの追加メソッドなどの拡張機能も提供します。

Promises / A +の標準Webサイトには、 1.0および1.1準拠の実装のリストがあります 。 A +標準に基づくプロミスコールバックは、イベントループで常にマイクロタスクとして非同期に実行されます

プロミスチェーン

then 、約束の方法は新しい約束を返す。

const promise = new Promise(resolve => setTimeout(resolve, 5000));

promise
    // 5 seconds later
    .then(() => 2)
    // returning a value from a then callback will cause
    // the new promise to resolve with this value
    .then(value => { /* value === 2 */ });

返すPromiseからthen 、コールバックすることは約束チェーンに追加します。

function wait(millis) {
    return new Promise(resolve => setTimeout(resolve, millis));
}

const p = wait(5000).then(() => wait(4000)).then(() => wait(1000));
p.then(() => { /* 10 seconds have passed */ });

catchどのように似て、拒否された約束が回復することができますcatchtry / catchステートメントが動作します。いずれかが連鎖しthenの後にcatchから解決された値使用して、その解決のハンドラを実行しますcatch

const p = new Promise(resolve => {throw 'oh no'});
p.catch(() => 'oh yes').then(console.log.bind(console));  // outputs "oh yes"

チェーンの途中にcatchまたはrejectハンドラがない場合、最後のcatchはチェーン内の拒否を捕捉します。

p.catch(() => Promise.reject('oh yes'))
  .then(console.log.bind(console))      // won't be called
  .catch(console.error.bind(console));  // outputs "oh yes"

場合によっては、関数の実行を「分岐」したい場合があります。あなたは、条件に応じて関数から異なる約束を返すことによってそれを行うことができます。コードの後半では、これらのブランチのすべてを1つに統合して、それらのブランチ上の他の関数を呼び出したり、すべてのエラーを1か所で処理したりすることができます。

promise
    .then(result => {          
        if (result.condition) {
            return handlerFn1() 
                .then(handlerFn2);
        } else if (result.condition2) {
            return handlerFn3()
                .then(handlerFn4);
        } else {
            throw new Error("Invalid result");
        }
    })
    .then(handlerFn5)
    .catch(err => {
        console.error(err);
    });

したがって、関数の実行順序は次のようになります。

promise --> handlerFn1 -> handlerFn2 --> handlerFn5 ~~> .catch()
         |                            ^
         V                            |
         -> handlerFn3 -> handlerFn4 -^            

単一のcatchは、発生する可能性がある分岐のいずれかでエラーを取得します。

前書き

Promiseオブジェクトは、値を生成しか、最終的に値を生成する操作を表します。プロミスは、非同期作業の結果(おそらく保留状態)を包み込み、深くネストされたコールバック(「 コールバック・ヘル 」と呼ばれる)の問題を緩和する強力な方法を提供します

状態と制御フロー

約束は、次の3つの状態のいずれかになります。

  • 保留中 - 基本操作はまだ完了しておらず、約束は保留中です。
  • fulfilled - オペレーションは終了し、約束は値で 満たさます 。これは、同期関数から値を返すことに似ています。
  • rejected - 操作中にエラーが発生し、約束が理由で 拒否されました。これは、同期関数にエラーを投げることに似ています。

約束が成立したとき、または拒絶されたときに約束された(または解決された )という。約束がいったん解決すれば、それは不変になり、その状態は変わることができません。その約束のthenメソッドとcatchメソッドを使用して、決済時に実行されるコールバックをアタッチすることができます。これらのコールバックは、それぞれフルフィルメント値と拒否理由で呼び出されます。

約束フロー図

const promise = new Promise((resolve, reject) => {
    // Perform some work (possibly asynchronous)
    // ...

    if (/* Work has successfully finished and produced "value" */) {
        resolve(value);
    } else {
        // Something went wrong because of "reason"
        // The reason is traditionally an Error object, although
        // this is not required or enforced.
        let reason = new Error(message);
        reject(reason);

        // Throwing an error also rejects the promise.
        throw reason;
    }
});

thenおよびcatchメソッドは、フルフィルメントおよび拒否コールバックを添付するために使用できます。

promise.then(value => {
    // Work has completed successfully,
    // promise has been fulfilled with "value"
}).catch(reason => {
    // Something went wrong,
    // promise has been rejected with "reason"
});

注:同じ約束でpromise.then(...)promise.catch(...)を呼び出すと、約束を実行している間、またはコールバックの中でエラーが発生した場合、 Uncaught exception in Promiseが発生する可能性があります。好ましい方法は、以前から返された約束を次のリスナーを添付するだろうthen / catch

あるいは、両方のコールバックを1回の呼び出しでアタッチすると、次のようにthenます。

promise.then(onFulfilled, onRejected);

すでに確定されている約束にコールバックを添付すると、即座にそれらがマイクロタスクキュー置かれ、「できるだけ早く」(つまり、現在実行中のスクリプトの直後に)呼び出されます。他の多くのイベントを実行する実装とは異なり、コールバックをアタッチする前に約束の状態を確認する必要はありません。


ライブデモ

遅延関数呼び出し

setTimeout()メソッドは、指定されたミリ秒後に関数を呼び出したり、式を評価したりします。これは、非同期操作を実現するための些細な方法でもあります。

この例では、 wait関数を呼び出すと、最初の引数として指定された時間後に約束が解決されます。

function wait(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));  
}

wait(5000).then(() => { 
    console.log('5 seconds have passed...');
});

同時に複数の約束を待っている

Promise.all()静的メソッドは、約束のPromise.all()例えばArray )を受け取り、 Promise.all()内のすべての約束が解決されたときに解決する新しい約束を返すか、またはイテラブル内の約束事の少なくとも1つが却下された場合に拒絶する。

// wait "millis" ms, then resolve with "value"
function resolve(value, milliseconds) {
    return new Promise(resolve => setTimeout(() => resolve(value), milliseconds));
}

// wait "millis" ms, then reject with "reason"
function reject(reason, milliseconds) {
    return new Promise((_, reject) => setTimeout(() => reject(reason), milliseconds));
}

Promise.all([
    resolve(1, 5000),
    resolve(2, 6000),
    resolve(3, 7000)    
]).then(values => console.log(values)); // outputs "[1, 2, 3]" after 7 seconds.

Promise.all([
    resolve(1, 5000),
    reject('Error!', 6000),
    resolve(2, 7000)
]).then(values => console.log(values)) // does not output anything
.catch(reason => console.log(reason)); // outputs "Error!" after 6 seconds.

イテラブル内の非約束値は約束されている

Promise.all([
    resolve(1, 5000),
    resolve(2, 6000),
    { hello: 3 }
])
.then(values => console.log(values)); // outputs "[1, 2, { hello: 3 }]" after 6 seconds

破壊の割り当ては、複数の約束から結果を取り出すのに役立ちます。

Promise.all([
    resolve(1, 5000),
    resolve(2, 6000),
    resolve(3, 7000)
])
.then(([result1, result2, result3]) => {
    console.log(result1);
    console.log(result2);
    console.log(result3);
});

最初の複数の約束を待っている

Promise.race()静的メソッドは、Promiseの反復可能性を受け取り、反復可能性の中の最初の約束が解決または拒否されるとすぐに解決または拒否する新しいPromiseを返します。

// wait "milliseconds" milliseconds, then resolve with "value"
function resolve(value, milliseconds) {
    return new Promise(resolve => setTimeout(() => resolve(value), milliseconds));
}

// wait "milliseconds" milliseconds, then reject with "reason"
function reject(reason, milliseconds) {
    return new Promise((_, reject) => setTimeout(() => reject(reason), milliseconds));
}

Promise.race([
    resolve(1, 5000),
    resolve(2, 3000),
    resolve(3, 1000)
])
.then(value => console.log(value)); // outputs "3" after 1 second.


Promise.race([
    reject(new Error('bad things!'), 1000),
    resolve(2, 2000)
])
.then(value => console.log(value)) // does not output anything
.catch(error => console.log(error.message)); // outputs "bad things!" after 1 second

「約束する」値

Promise.resolve静的メソッドを使用して、値を約束にラップすることができます。

let resolved = Promise.resolve(2);
resolved.then(value => {
    // immediately invoked
    // value === 2
});

valueがすでに約束されている場合、 Promise.resolve単にそれを再作成します。

let one = new Promise(resolve => setTimeout(() => resolve(2), 1000));
let two = Promise.resolve(one);
two.then(value => {
    // 1 second has passed
    // value === 2
});

実際には、 valueは、 "thenable"(spec準拠の約束と同様に十分機能するthenメソッドを定義するオブジェクト)になります。これにより、 Promise.resolveは、信頼できない第三者のオブジェクトを信頼できる第三者の約束に変換することができます。

let resolved = Promise.resolve({
    then(onResolved) {
        onResolved(2);
    }
});
resolved.then(value => {
    // immediately invoked
    // value === 2
});

Promise.reject静的メソッドは、特定のreasonですぐに拒否する約束を返します。

let rejected = Promise.reject("Oops!");
rejected.catch(reason => {
    // immediately invoked
    // reason === "Oops!"
});

コールバックによる「特化」機能

ノードスタイルのコールバックを受け入れる関数が与えられた場合、

fooFn(options, function callback(err, result) { ... });

これを約束することができます(約束事に基づく関数に変換する)

function promiseFooFn(options) {
    return new Promise((resolve, reject) =>
        fooFn(options, (err, result) =>
            // If there's an error, reject; otherwise resolve
            err ? reject(err) : resolve(result)
        )
    );
}

この関数は、次のように使用できます。

promiseFooFn(options).then(result => {
    // success!
}).catch(err => {
    // error!
});

もっと一般的な方法として、与えられたコールバックスタイルの関数を約束する方法は次のとおりです:

function promisify(func) {
    return function(...args) {
        return new Promise((resolve, reject) => {
            func(...args, (err, result) => err ? reject(err) : resolve(result));
        });
    }
}

これは次のように使用できます:

const fs = require('fs');
const promisedStat = promisify(fs.stat.bind(fs));

promisedStat('/foo/bar')
    .then(stat => console.log('STATE', stat))
    .catch(err => console.log('ERROR', err));

エラー処理

約束からスローされたエラーは、(第2パラメータによって処理されるreject )に渡されたthenまたはに渡されたハンドラによってcatch

throwErrorAsync()
  .then(null, error => { /* handle error here */ });
// or
throwErrorAsync()
  .catch(error => { /* handle error here */ });

チェイニング

プロミスチェーンを使用している場合、エラーが発生resolveresolveハンドラはスキップされます。

throwErrorAsync()
  .then(() => { /* never called */ })
  .catch(error => { /* handle error here */ });

同じことがthen機能にも当てはまります。 resolveハンドラが例外をスローすると、次のrejectハンドラが呼び出されます。

doSomethingAsync()
  .then(result => { throwErrorSync(); })
  .then(() => { /* never called */ })
  .catch(error => { /* handle error from throwErrorSync() */ });

エラーハンドラは新しい約束を返し、約束を続けることができます。エラーハンドラによって返された約束は、ハンドラによって返された値で解決されます。

throwErrorAsync()
  .catch(error => { /* handle error here */; return result; })
  .then(result => { /* handle result here */ });

エラーを再スローすることで、エラーを約束することができます:

throwErrorAsync()
  .catch(error => {
      /* handle error from throwErrorAsync() */
      throw error;
  })
  .then(() => { /* will not be called if there's an error */ })
  .catch(error => { /* will get called with the same error */ });

setTimeoutコールバック内にthrow文をラップすることで、promiseによって処理されない例外をスローすることができます。

new Promise((resolve, reject) => {
  setTimeout(() => { throw new Error(); });
});

これは、プロビジョニングが非同期にスローされた例外を処理できないために機能します。

未処理の拒否

promiseにcatchブロックまたはrejectハンドラがない場合、エラーは暗黙のうちに無視されます。

throwErrorAsync()
  .then(() => { /* will not be called */ });
// error silently ignored

これを防ぐには、常にcatchブロックを使用します。

throwErrorAsync()
  .then(() => { /* will not be called */ })
  .catch(error => { /* handle error*/ });
// or
throwErrorAsync()
  .then(() => { /* will not be called */ }, error => { /* handle error*/ });

また、に加入unhandledrejection未処理の拒否約束をキャッチするイベント:

window.addEventListener('unhandledrejection', event => {});

いくつかの約束は、彼らの創造時より後に拒絶を処理することができます。そのような約束事が処理されるときはいつでも、 rejectionhandledイベントが発生します。

window.addEventListener('unhandledrejection', event => console.log('unhandled'));
window.addEventListener('rejectionhandled', event => console.log('handled'));
var p = Promise.reject('test');

setTimeout(() => p.catch(console.log), 1000);

// Will print 'unhandled', and after one second 'test' and 'handled'

event引数には拒否に関する情報が含まれます。 event.reasonはエラーオブジェクトで、 event.promiseはイベントを引き起こした約束オブジェクトです。

Nodejsにrejectionhandledunhandledrejectionイベントが呼び出されるrejectionHandledunhandledRejection上のprocess 、それぞれ異なる署名を有します。

process.on('rejectionHandled', (reason, promise) => {});
process.on('unhandledRejection', (reason, promise) => {});

reason引数はエラーオブジェクトであり、 promise引数はイベントを発生させたpromiseオブジェクトへの参照です。

これらのunhandledrejectionていないrejectionhandledイベントとrejectionhandled unhandledrejectionイベントは、デバッグの目的でのみ使用する必要があります。通常、すべての約束は拒絶を処理するべきです。

注:現時点では、Chrome 49+とNode.jsのみがunhandledrejection rejectionhandledイベントとrejectionhandled unhandledrejectionイベントをサポートしています。

警告

fulfillreject連鎖reject

then(fulfill, reject)関数(両方のパラメータがnullない)は、一意かつ複雑な振る舞いを持ち、正確な動作が分からない限りは使用しないでください。

入力の1つにnullが指定されていると、関数は期待通りに機能しnull

// the following calls are equivalent
promise.then(fulfill, null) 
promise.then(fulfill)

// the following calls are also equivalent
promise.then(null, reject) 
promise.catch(reject)

しかし、両方の入力が与えられたとき、それは独特の挙動をとる:

// the following calls are not equivalent!
promise.then(fulfill, reject)
promise.then(fulfill).catch(reject)

// the following calls are not equivalent!
promise.then(fulfill, reject)
promise.catch(reject).then(fulfill)

then(fulfill, reject)関数は、 then(fulfill).catch(reject)ショートカットのように見えますが、互換性がないと問題を引き起こします。このような問題の一つは、ということですrejectハンドラはからのエラー処理しないfulfillハンドラを。起こることは次のとおりです。

Promise.resolve() // previous promise is fulfilled
    .then(() => { throw new Error(); }, // error in the fulfill handler
        error => { /* this is not called! */ });

上記のコードは、エラーが伝搬されるため、約束が拒否されます。これを次のコードと比較すると、約束が成就します。

Promise.resolve() // previous promise is fulfilled
    .then(() => { throw new Error(); }) // error in the fulfill handler
    .catch(error => { /* handle error */ });

同様の問題はthen(fulfill, reject)された約束の代わりに約束された約束を伝播することを除いて、 catch(reject).then(fulfill)

同期的に約束を返すべき関数から投げる

このような関数を想像してみてください。

function foo(arg) {
  if (arg === 'unexepectedValue') {
    throw new Error('UnexpectedValue')
  }

  return new Promise(resolve => 
    setTimeout(() => resolve(arg), 1000)
  )
}

もしそのような関数がpromiseチェーンの途中で使われるなら、明らかに問題はありません:

makeSomethingAsync().
  .then(() => foo('unexpectedValue'))
  .catch(err => console.log(err)) // <-- Error: UnexpectedValue will be caught here

しかし、同じ関数がpromise chainの外で呼び出された場合、エラーはそれによって処理されず、アプリケーションにスローされます。

foo('unexpectedValue') // <-- error will be thrown, so the application will crash
  .then(makeSomethingAsync) // <-- will not run
  .catch(err => console.log(err)) // <-- will not catch

回避策は2つあります。

エラーで拒否された約束を返す

スローするのではなく、次のようにします。

function foo(arg) {
  if (arg === 'unexepectedValue') {
    return Promise.reject(new Error('UnexpectedValue'))
  }

  return new Promise(resolve => 
    setTimeout(() => resolve(arg), 1000)
  )
}

あなたの機能を約束する

あなたのthrowステートメントは、すでにプロミスチェーン内にあるときに適切に捕捉されます:

function foo(arg) {
  return Promise.resolve()
    .then(() => {
      if (arg === 'unexepectedValue') {
        throw new Error('UnexpectedValue')
      }

      return new Promise(resolve => 
        setTimeout(() => resolve(arg), 1000)
      )
    })
}

同期操作と非同期操作の調整

場合によっては、コード・ブランチでの反復を防ぐために、同期操作を約束の中にラップしたい場合があります。この例を考えてみましょう:

if (result) { // if we already have a result
  processResult(result); // process it
} else {
  fetchResult().then(processResult);
}

上記のコードの同期および非同期の分岐は、同期操作を約束の中に冗長にラップすることで調整できます。

var fetch = result
  ? Promise.resolve(result)
  : fetchResult();

fetch.then(processResult);

非同期呼び出しの結果をキャッシュするときは、結果自体ではなく約束をキャッシュすることが望ましい。これにより、複数の並列要求を解決するために必要な非同期操作が1つだけになります。

エラー状態が発生したときにキャッシュされた値を無効にするように注意する必要があります。

// A resource that is not expected to change frequently
var planets = 'http://swapi.co/api/planets/';
// The cached promise, or null
var cachedPromise;

function fetchResult() {
    if (!cachedPromise) {
        cachedPromise = fetch(planets)
            .catch(function (e) {
                // Invalidate the current result to retry on the next fetch
                cachedPromise = null;
                // re-raise the error to propagate it to callers
                throw e;
            });
    }
    return cachedPromise;
}

連鎖を約束するように配列を減らす

このデザインパターンは、要素のリストから一連の非同期アクションを生成するのに便利です。

2つの変種があります:

  • チェーンが成功を収めている限り継続するチェーンを構築する「引き下げ」の削減です。
  • チェーンがエラーを経験している限り継続するチェーンを構築する「キャッチ」リダクション。

"then" reduction

パターンのこの変形は、 .then()チェーンを構築し、アニメーションを連鎖させたり、一連の従属HTTPリクエストを作成するために使用されます。

[1, 3, 5, 7, 9].reduce((seq, n) => {
    return seq.then(() => {
        console.log(n);
        return new Promise(res => setTimeout(res, 1000));
    });
}, Promise.resolve()).then(
    () => console.log('done'),
    (e) => console.log(e)
);
// will log 1, 3, 5, 7, 9, 'done' in 1s intervals

説明:

  1. 我々は、呼び出し.reduce()ソースアレイ上、及び提供Promise.resolve()初期値として。
  2. すべての要素を減らすと、 .then()が初期値に追加されます。
  3. reduce()の商品はPromise.resolve()、then(...)、then(...)になります。
  4. 私たちは、手動で追加.then(successHandler, errorHandler)減らす後に実行するために、 successHandler以前のすべての手順が解決したら。いずれかのステップが失敗すると、 errorHandlerが実行されます。

注: "then"リダクションは、 Promise.all()シーケンシャルカウンターパートです。

「キャッチ」削減

パターンのこの変形は、 .catch()チェーンを構築し、動作中のサーバが見つかるまで、一連のWebサーバを一連のミラー化されたリソースに対して順次探索するために使用されることがあります。

var working_resource = 5; // one of the values from the source array
[1, 3, 5, 7, 9].reduce((seq, n) => {
    return seq.catch(() => {
        console.log(n);
        if(n === working_resource) { // 5 is working
            return new Promise((resolve, reject) => setTimeout(() => resolve(n), 1000));
        } else { // all other values are not working
            return new Promise((resolve, reject) => setTimeout(reject, 1000));
        }
    });
}, Promise.reject()).then(
    (n) => console.log('success at: ' + n),
    () => console.log('total failure')
);
// will log 1, 3, 5, 'success at 5' at 1s intervals

説明:

  1. 我々は、呼び出し.reduce()ソースアレイ上、及び提供Promise.reject()初期値として。
  2. すべての要素を減らすと、 .catch()が初期値に追加されます。
  3. reduce()の製品はPromise.reject().catch(...).catch(...)ます。
  4. 我々は、手動で追加する.then(successHandler, errorHandler)実行するために、削減後successHandler 、前のステップのいずれかが解決した後。すべてのステップが失敗すると、 errorHandlerが実行されます。

注意:「キャッチ」削減は、 Promise.any()逐次的な対応ですPromise.any() bluebird.jsで実装されていますが、現在ネイティブのECMAScriptでは実装されていません)。

forEachと約束

配列の各要素に約束を返す関数( cb )を効果的に適用することができます。各要素は、前の要素が処理されるまで処理されるのを待っています。

function promiseForEach(arr, cb) {
  var i = 0;

  var nextPromise = function () {
    if (i >= arr.length) {
      // Processing finished.
      return;
    }

    // Process next function. Wrap in `Promise.resolve` in case
    // the function does not return a promise
    var newPromise = Promise.resolve(cb(arr[i], i));
    i++;
    // Chain to finish processing.
    return newPromise.then(nextPromise);
  };

  // Kick off the chain.
  return Promise.resolve().then(nextPromise);
};

これは、一度に1つずつ、何千ものアイテムを効率的に処理する必要がある場合に役立ちます。定期的なforループを使用して約束を作成すると、それらをまとめて作成し、かなりの量のRAMを占有します。

finally()でクリーンアップを実行する

現在、約束が満たされたか拒否されたかにかかわらず実行される約束にfinallyコールバックを追加する提案 (ECMAScript標準の一部ではない)があります。意味的には、これはtryブロックのfinally節に似ています

通常、この機能をクリーンアップに使用します。

var loadingData = true;

fetch('/data')
    .then(result => processData(result.data))
    .catch(error => console.error(error))
    .finally(() => {
        loadingData = false;
    });

finallyコールバックは約束の状態に影響しないことに注意することが重要です。それがどんな価値を返すかは関係ありません。約束は以前にあった満たされた/拒絶された状態のままです。したがって、上記の例では、 finallyコールバックがundefined返しても、 processData(result.data)processData(result.data)戻り値で解決されます。

標準化プロセスがまだ進行中であるため、あなたの約束の実装はfinallyコールバックをそのまま受け入れないでしょう。同期コールバックの場合は、ポリフィルを使用してこの機能を追加できます。

if (!Promise.prototype.finally) {
    Promise.prototype.finally = function(callback) {
        return this.then(result => {
            callback();
            return result;
        }, error => {
            callback();
            throw error;
        });
    };
}

非同期APIリクエスト

これは、非同期機能を利用することを約束した簡単なGET API呼び出しの例です。

var get = function(path) {
  return new Promise(function(resolve, reject) {
    let request = new XMLHttpRequest();
    request.open('GET', path);
    request.onload = resolve;
    request.onerror = reject;
    request.send();
  });
};

より堅牢なエラー処理は、次のonload関数とonerror関数を使用して実行できます。

request.onload = function() {
  if (this.status >= 200 && this.status < 300) {
    if(request.response) {
      // Assuming a successful call returns JSON
      resolve(JSON.parse(request.response));
    } else {
      resolve();
  } else {
    reject({
      'status': this.status,
      'message': request.statusText
    });
  }
};

request.onerror = function() {
  reject({
    'status': this.status,
    'message': request.statusText
  });
};

ES2017 async / awaitを使用する

上の同じ例のImage loadingはasync関数を使って記述することができます。これにより、例外処理のために共通のtry/catchメソッドを使用することもできます。

注: 2017年4月現在、Internet Explorer以外のすべてのブラウザの現在のリリースでは、非同期機能がサポートされています

function loadImage(url) {
    return new Promise((resolve, reject) => {
        const img = new Image();
        img.addEventListener('load', () => resolve(img));
        img.addEventListener('error', () => {
            reject(new Error(`Failed to load ${url}`));
        });
        img.src = url;
    });
}

(async () => {

    // load /image.png and append to #image-holder, otherwise throw error
    try {
        let img = await loadImage('http://example.com/image.png');
        document.getElementById('image-holder').appendChild(img);
    }
    catch (error) {
        console.error(error);
    }

})();


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow