5
5

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.

JavaScriptのPromiseを説明しようぜ☆(^q^)

Last updated at Posted at 2018-08-22

だらだらと書く。

async/await を使えだぜ。Promise を簡単にしたやつだぜ。
だが レガシーのリプレースマンは両方知っておく必要があるはめになる。 async/await、Promise の両方を説明する。

コードは試してないが 思い出して書くと、

let promise = new Promise((resolve, reject) => {
    resolve();
});

こんな感じで Promise オブジェクトを作る。すると、

// パターン1
promise
.then(() => {
},
err => {
});

と書くか、

// パターン2
promise
.then(() => {
})
.catch(err => {
});

といったように書いて使う。

  • パターン1は then に対応したエラー処理を書きたいとき。
  • パターン2は エラー処理を1回で済ませたいとき。

につかう。エラーは reject(new Error('エラーメッセージ')); のように書いて使う。

まだ続く。

thenチェーン

promise
.then(() => {
    return new Promise((resolve, reject) => {
        resolve();
    });
})
.then(() => {
})
.catch(err => {
});

.then の中で プロミスを返すと、.then の返り値は Promise なので
.then をつなげることができる。

Promiseコンストラクターの引数に渡しているコールバック関数は、
制御が抜けてもブロックしていて、resolve() か、 reject() が実行されるまで
ブロックしている。

resolve()の引数は、.thenのコールバック関数の引数に渡される。

promise
.then(() => {
    return new Promise((resolve, reject) => {
        // ここで引数を1つだけ渡せる。オブジェクトにするとお得。
        resolve({
            name: 'わはは',
            age: 49
        });
    });
})
// resolve で渡された内容はこの result に入っている。
.then((result) => {
    console.log('name: ' + result.name + ' age: ' + result.age);
})
.catch(err => {
});

こんな気分。

プロミスの配列をイテレートする。

Promise.all() 関数と、 Promise.race() 関数がある。はしょって all の方だけ説明する。

let promiseArray = [];
// promiseArray 配列に、豪快に Promise をいっぱい追加するとする。

Promise.all(promiseArray)
.then((resultArray) => {
    // promiseArray が全部終わったらここにくる。
    // resultArray は、プロミスの配列。promiseArray と同じ順序で入っている。
})
.catch(err => {
});

100個ぐらい SQL叩きたいときとか、 .then を 100個もつなげたくないんで、
Promise.all() を使えだぜ。 all の返り値も Promise。

async/await の使い方。

  • 条件1. await を使っている関数の頭には async とつける。
### 例1
async function () {
    let returns = await func1();
}

### 例2
async () => {
    let returns = await func1();
};

頭に async を付けた関数は Promise インスタンスを返すようになる。つまり、

### これと
async () => {
    return 'あいうえお';
};

### これは 同じ
() => {
    return new Promise((resolve, reject) => {
        resolve('あいうえお');
    });
};

async の方が見やすいぜ。

  • 条件2. Promise オブジェクトの頭には await を付けれる。
### 
let returns = await new Promise ((resolve, reject) => {
    return 'あいうえお';
});

### 以下のコードと同等
new Promise ((resolve, reject) => {
    resolve('あいうえお');
})
.then((returns) => {
});

await は、 .then( ) の代わりをする。

  • 条件3. reject(err); の代わりに throw err; を使う。
### 
try {
    let returns = await new Promise ((resolve, reject) => {
        if (/*エラーが起こった時*/) {
            throw new Error('エラー');
        } else {
            return 'あいうえお';
        }
    });
} catch (err) {
    /* エラー処理 */
}

### 下のコードと同等
new Promise ((resolve, reject) => {
    if (/*エラーが起こった時*/) {
        reject('エラー');
    } else {
        result('あいうえお');
    }
})
.then((returns) => {
})
.catch((err) => {
    /* エラー処理 */
})
;

try - catch 構文の方が、ネストが少なく見やすい。

  • resolve(x); の代わりに return x; を使うが、ただし、関数を抜けるときの暗黙の return はブロックしないので 制御が抜け落ちてしまう。 これを防ぐには、
    関数の中の非同期部分を全部 await に書き換えたタイミングで new Promise((resolve,reject) => {}); の囲いを外していくといいだろう。
5
5
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
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?