JavaScript非同期プログラミングの4つの方法
4960 ワード
非同期プログラミングは、JavaScriptを使用してプログラムを作成する人ごとに発生する問題であり、フロントエンドのajax要求、またはnodeの様々な非同期APIに関係なく.本論文では,一般的な四つの非同期プログラミングを扱う方法をまとめた.
コールバック関数
コールバック関数を使用するのは最も一般的な形式で、いくつかの例を挙げます.
コールバック関数の欠点は、複数の非同期動作を実行すると複数のコールバック関数がネストされ、コード構造が乱れ、コールバック地獄と呼ばれる.
Promiseは、チェーンで呼び出された方法で非同期コードを組織し、元のコールバック関数として呼び出されたコードをチェーン式呼出しに変更することができます.
Generators
nodeの有名な開発者TJは、ES 6の新特性生成器(Generators)を用いて、非同期制御ツールcoを開発した.
Generatorsを知らないなら、以下の文章を見てもいいです.深浅浅出ES 6(3):ジェネレータGenerators 深入りES 6(11):ジェネレータGenerators、続編 coを利用して、同期コードのような書き方ができます.
Async/Await
node 7.6以上のバージョンはES 7の新しい特性を導入しました.Aync/Awaitは非同期コードを制御するために専用です.まず例を見ます.
Generators制御方式とは大きく違っているように見えますが、Aync/Awaitは元々非同期をコントロールするために使われていますので、おすすめです.
エラー処理
最後に、次の4つの非同期制御方法のエラー処理を検討する.
コールバック関数
コールバック関数のエラー処理はとても簡単です.コールバック関数でエラーメッセージを同時に送ることです.
Promiseは、
GeneratorsとAync/Awaitは比較的に類似しており、第一にPromiseを使用する
Promise catch
参照 ES 6のPromiseオブジェクトについて話す 深浅浅出ES 6(3):ジェネレータGenerators 深入りES 6(11):ジェネレータGenerators、続編 この記事は私の個人ブログと同期します.http://blog.acwong.org/2017/06/24/javascript-async-programming/
コールバック関数
コールバック関数を使用するのは最も一般的な形式で、いくつかの例を挙げます.
// jQuery ajax
$.get('test.html', data => {
$('#result').html(data)
})
// node
const fs = require('fs')
fs.readFile('/etc/passwd', (err, data) => {
if (err) {
throw err
}
console.log(data)
})
コールバック関数は、関数を定義する際に別の関数(コールバック関数)をパラメータとして定義された関数に導入し、非同期動作が実行された後にこのコールバック関数を実行することで、次の動作が非同期動作の後に実行されることを確認することができます.コールバック関数の欠点は、複数の非同期動作を実行すると複数のコールバック関数がネストされ、コード構造が乱れ、コールバック地獄と呼ばれる.
func1(data0, data1 => {
func2(data2, data3 => {
func3(data3, data4 => data4)
})
})
PromisePromiseは、チェーンで呼び出された方法で非同期コードを組織し、元のコールバック関数として呼び出されたコードをチェーン式呼出しに変更することができます.
// jQuery ajax promise
$.get('test.html')
.then(data => $(data))
.then($data => $data.find('#link').val('href'))
.then(href => console.log(href))
自分でプロモーション形式を定義する関数はES 6の中でも非常に簡単です.function ready() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ready')
}, 3000)
})
}
ready().then(ready => console.log(`${ready} go!`))
node 8.0以上のバージョンでは、util.promisify
方法を用いて、コールバック形式の関数をPromise形式に変更することもできる.const util = require('util')
const fs = require('fs')
const readPromise = util.promisify(fs.readFile)
readPromise('test.txt').then(data => console.log(data.toString()))
Promiseを詳しく知りたいですが、拙作を読んでES 6のPromiseオブジェクトについて話してもいいです.Generators
nodeの有名な開発者TJは、ES 6の新特性生成器(Generators)を用いて、非同期制御ツールcoを開発した.
Generatorsを知らないなら、以下の文章を見てもいいです.
const util = require('util')
const fs = require('fs')
const co = require('co')
const readFile = util.promisify(fs.readFile)
co(function* () {
const txt = yield readFile('file1.txt', 'utf8')
console.log(txt)
const txt2 = yield readFile('file2.txt', 'utf8')
console.log(txt2)
})
Generatorsを使っているのは明らかに分かりやすいようで、非同期コードをはっきりと書くことができます.Async/Await
node 7.6以上のバージョンはES 7の新しい特性を導入しました.Aync/Awaitは非同期コードを制御するために専用です.まず例を見ます.
const util = require('util')
const fs = require('fs')
const readFile = util.promisify(fs.readFile)
async function readFiles () {
const txt = await readFile('file1.txt', 'utf8')
console.log(txt)
const txt2 = await readFile('file2.txt', 'utf8')
console.log(txt2)
})
まず、async
のキーワードを使用して、非同期コードを含む関数を定義し、Promise形式の非同期関数の前にawait
のキーワードを使用すれば、非同期を同期動作として書き上げることができる.Generators制御方式とは大きく違っているように見えますが、Aync/Awaitは元々非同期をコントロールするために使われていますので、おすすめです.
エラー処理
最後に、次の4つの非同期制御方法のエラー処理を検討する.
コールバック関数
コールバック関数のエラー処理はとても簡単です.コールバック関数でエラーメッセージを同時に送ることです.
const fs = require('fs')
fs.readFile('file.txt', (err, data) => {
if (err) {
throw err
}
console.log(data)
})
PromisePromiseは、
then
方法の後に、エラー情報をキャプチャするためにcatch
スキームを使用する.const fs = require('fs')
const readFile = util.promisify(fs.readFile)
readFile('file.txt')
.then(data => console.log(data))
.catch(err => console.log(err))
GeneratorsとAync/AwaitGeneratorsとAync/Awaitは比較的に類似しており、第一にPromiseを使用する
catch
の方法があり、第二にtry
catch
のキーワードを使用する.Promise catch
const fs = require('fs')
const co = require('co')
const readFile = util.promisify(fs.readFile)
co(function* () {
const data = yield readFile('file.txt').catch(err => console.log(err))
})
const fs = require('fs')
const co = require('co')
const readFile = util.promisify(fs.readFile)
async function testRead() {
const data = await readFile('file.txt').catch(err => console.log(err))
}
try/catchconst fs = require('fs')
const co = require('co')
const readFile = util.promisify(fs.readFile)
co(function* () {
try {
const data = yield readFile('file.txt')
} catch(err) {
console.log(err)
}
})
const fs = require('fs')
const readFile = util.promisify(fs.readFile)
async function testRead() {
try {
const data = await readFile('file.txt')
} catch(err) {
console.log(data)
}
}
読んでいただいてありがとうございます.足りないところがあれば指摘してください.参照