JavaScript学習の非同期
11182 ワード
ここのコード例はここのasyncを参照してください.
目次引用 calback async �Promise Promiseオブジェクト ブルーバード Generator co async/await 小結 ことばを引く
JavaScript言語の実行環境が「単一スレッド」であることはよく知られていますが、同時にプログラムを作成するための敷居が大幅に低くなりました.
しかし、どうやってハードルを下げながら性能を確保しますか?承諾は異歩である
したがって、本論文ではJavaScriptの非同期プログラミングの方法を詳しく説明します.
calback
calbackはまたコールバックと呼ばれています.JavaScriptプログラミングの中で最も基本的な非同期処理方法です.
例えば、ファイルのコードを読み込む.
async
上記は手順のみで非同期フィードバックを実行する簡単な例です.より複雑な非同期制御を実現するために、第三者のライブラリasyncを利用してもいいです.
asyncの基本的な制御プロセスは以下の三つです. seriesシーケンスは実行されますが、データインタラクションがありません.
例えば上記のようにファイルを読み込む例はasyncを使って実現されます.
babel-nodeを使ってasync.jsファイルの印刷結果は以下の通りです. parallel並列実行 複数のファイルを同時に読み込む機能を実現したいなら、asyncを使って実現します. waterfall順序で実行され、データインタラクションがある
Promise
簡単なプロジェクトにとって、上述のasync方式を使うと完全に需要を満たすことができます.
しかし、リピーターベースの方法は複雑なプロジェクトの中ではまだ簡潔ではないです.
そのため、Promiseに基づく非同期方法が生まれました.
Promiseを使う前に、Promiseとは何かを明確にする必要がありますか?
Promiseは非同期プログラミングのための統一インターフェースを提供することを目的としています.
Promiseを使う時、インターフェースはどのように統一されていますか?
Promiseの原理と使用を知ると、Promiseにパッケージされたコードを呼び出すことができます.
しかし、もし自分でPromiseを封入する必要があったら、どうすればいいですか?
�ES 6提供のPromiseオブジェクトが使用できます.
ES 6及びJavaScriptバージョンについての詳細な紹介はJavaScript学習のバージョンを参照することができます.
例えば、ファイルを読み込むための非同期動作は、以下のようにPromiseオブジェクトにパッケージ化することができる.
上記の自分でPromiseオブジェクトをカプセル化する方法以外に、第三者ライブラリbluebirdを借りることができます.
bluebird以外にもPromiseを実現するための第三のライブラリがあります.例えばq、bluebirdに関するもっと多い比較と紹介はWhat's the difference between Q、Bluebird、and Ayncを参照してもいいです.
上記Promiseオブジェクトを使用して実現された例については、bluebirdを用いて以下のように実現されています.
babel-nodeを使ってbluebird.jsファイルの印刷結果は以下の通りです.
PromiseはCallback Hellの問題を解決できますが、チェーンのコードはまだ直観的ではないようです.
従ってES 6にはGenerator関数が導入され、またジェネレータ関数と呼ばれる.
Generator関数と一般関数の違いは、functionの後ろに星番号を追加したということです.すなわち、function*
例えば、以下のGenerator関数を用いて、ファイルを読み込む例
Generator関数を呼び出して返したのはGeneratorオブジェクトですが、コードはyieldで実行を一時停止します.
Generatorオブジェクトのnext()メソッドコードを実行し続けて次のyieldに一時停止します.
上记のように、コードは一回だけnext()メソッドを実行していますので、file 1.txtを読んでから停止します.
したがって、Babel-nodeを使ってgenerator.jsファイルの印刷結果は以下の通りです.
Generator関数は目的は良いですが、理解と使用が不便なので、神器coがあります.
これはGenerator関数を自動的に実行するために、開発者がGeneratorオブジェクトを手動で作成する必要がないようにし、next()を呼び出す方法です.
coを使った後に非同期のコードはこのように見えます.
babel-nodeでco.jsファイルを実行して印刷します.結果は以下の通りです.
co()はPromiseに戻ります.
coパッケージのGenerator関数の中のyieldの後ろはPromiseでなければなりません.
上記のcoの基本的な使い方以外にも、coを使ってGenerator関数を普通の関数にカプセル化することができます.
また、coのソースコードは200行以上しかありません.中には多くのコメントと空行が含まれています.
async/await
异歩の「究极」に感慨を覚えたばかりだ.coとGeneratorはなぜまだ物语が终わっていないのか?
理由は簡単です.JavaScript言語の原生も同じようなcoを入れてGeneratorの実現に協力しました.async/await
ここのasyncはJavaScriptの最新バージョンの中で非同期のキーワードを実現して前に紹介した第三者の倉庫asyncと混同しないでください.
総じてオリジナルの方がいいですので、co公式ではasync/awaitを使うことを勧めています.
このことが思い出されます.iPhoneの脱獄プラグインの多くは最新バージョンのiOSに組み込まれていますので、脱獄に興味を持つ人が多くなりました.
余談はないですが、そのままオリジナルの異歩「究極の神器」を見てみましょう.
async/awaitを使う前にまずbabelを配置して依存を追加する必要があります.
続いてJavaScript言語の原生のasync/awaitを使うことができます.
async/awaitと一般関数の使い方はほとんど同じです.
唯一の違いは、functionの前にasyncを加えて関数内のPromiseの前にawaitを加えることです.
結び目
最後にもう一度JavScriptの非同期プログラムの完全な進展過程を振り返ってみます.
参照 Async詳細解の一つ:フロー制御 枚の図学会はAsyncコンポーネントを用いて非同期フロー制御を行う . Promiseオブジェクト Javascript非同期プログラミングの4つの方法 Node.js最新技術スタックのPromise編 Generator関数の意味と使い方 yieldとyield* co関数ライブラリの意味と使い方 Babel入門教程 もっと多くの文章を、私の個人ブログを応援してください.
目次
JavaScript言語の実行環境が「単一スレッド」であることはよく知られていますが、同時にプログラムを作成するための敷居が大幅に低くなりました.
しかし、どうやってハードルを下げながら性能を確保しますか?承諾は異歩である
したがって、本論文ではJavaScriptの非同期プログラミングの方法を詳しく説明します.
calback
calbackはまたコールバックと呼ばれています.JavaScriptプログラミングの中で最も基本的な非同期処理方法です.
例えば、ファイルのコードを読み込む.
// callback.js
var fs = require('fs');
fs.readFile('file1.txt', function (err, data) {
console.log("file1.txt: " + data.toString());
fs.readFile('file2.txt', function (err, data) {
console.log("file2.txt: " + data.toString());
fs.readFile('file3.txt', function (err, data) {
console.log("file3.txt: " + data.toString());
});
});
});
テストファイルの内容はそれぞれ// file1.txt
file1
// file2.txt
file2
// file3.txt
file3
babel-nodeを使ってcalback.jsファイルの印刷結果は以下の通りです.file1.txt: file1
file2.txt: file2
file3.txt: file3
Babel-nodeについてもっと紹介します.JavaScript学習のバージョンを参照してください.async
上記は手順のみで非同期フィードバックを実行する簡単な例です.より複雑な非同期制御を実現するために、第三者のライブラリasyncを利用してもいいです.
asyncの基本的な制御プロセスは以下の三つです.
series
parallel
waterfall
例えば上記のようにファイルを読み込む例はasyncを使って実現されます.
// async.js
var fs = require('fs');
var async = require('async');
async.series([
function (callback) {
fs.readFile('file1.txt', function (err, data) {
callback(null, 'file1.txt: ' + data.toString());
});
},
function (callback) {
fs.readFile('file2.txt', function (err, data) {
callback(null, 'file2.txt: ' + data.toString());
});
},
function (callback) {
fs.readFile('file3.txt', function (err, data) {
callback(null, 'file3.txt: ' + data.toString());
});
}
],
function (err, results) {
console.log(results);
});
asyncを使う前にインストールの依存が必要です.npm i--save asyncbabel-nodeを使ってasync.jsファイルの印刷結果は以下の通りです.
[ 'file1.txt: file1', 'file2.txt: file2', 'file3.txt: file3' ]
// async.js
async.parallel([
function (callback) {
fs.readFile('file1.txt', function (err, data) {
callback(null, 'file1.txt: ' + data.toString());
});
},
function (callback) {
fs.readFile('file2.txt', function (err, data) {
callback(null, 'file2.txt: ' + data.toString());
});
},
function (callback) {
fs.readFile('file3.txt', function (err, data) {
callback(null, 'file3.txt: ' + data.toString());
});
}
],
function (err, results) {
console.log(results);
});
babel-nodeを使ってasync.jsファイルの印刷結果は以下の通りです.[ 'file1.txt: file1', 'file2.txt: file2', 'file3.txt: file3' ]
ここのファイルは内容が小さいので、結果はまだ順序で実行されているように見えますが、実は並行して実行されています.// async.js
var fs = require('fs');
var async = require('async');
async.waterfall([
function (callback) {
fs.readFile('file1.txt', function (err, data) {
callback(null, 'file1.txt: ' + data.toString());
});
},
function (n, callback) {
fs.readFile('file2.txt', function (err, data) {
callback(null, [n, 'file2.txt: ' + data.toString()]);
});
},
function (n, callback) {
fs.readFile('file3.txt', function (err, data) {
callback(null, [n[0], n[1], 'file3.txt: ' + data.toString()]);
});
}
],
function (err, results) {
console.log(results);
});
babel-nodeを使ってasync.jsファイルの印刷結果は以下の通りです.[ 'file1.txt: file1', 'file2.txt: file2', 'file3.txt: file3' ]
もちろんasyncの機能はこれらだけではなく、autなどもっと強力なプロセスコントロールなどの読者が知りたいなら、ここを参考にしてください.Promise
簡単なプロジェクトにとって、上述のasync方式を使うと完全に需要を満たすことができます.
しかし、リピーターベースの方法は複雑なプロジェクトの中ではまだ簡潔ではないです.
そのため、Promiseに基づく非同期方法が生まれました.
Promiseを使う前に、Promiseとは何かを明確にする必要がありますか?
Promiseは非同期プログラミングのための統一インターフェースを提供することを目的としています.
Promiseを使う時、インターフェースはどのように統一されていますか?
return step1().then(step2).then(step3).catch(function(err){
// err
});
上記の例から、Promiseには以下の三つの特徴があることが分かります. Promise
then/catch
もちろん上述の手順以外にも、制御フローPromiseは並列実行の制御フローをサポートしています.var promise123 = Promise.all([promise1, promise2, promise3]);
PromiseオブジェクトPromiseの原理と使用を知ると、Promiseにパッケージされたコードを呼び出すことができます.
しかし、もし自分でPromiseを封入する必要があったら、どうすればいいですか?
�ES 6提供のPromiseオブジェクトが使用できます.
ES 6及びJavaScriptバージョンについての詳細な紹介はJavaScript学習のバージョンを参照することができます.
例えば、ファイルを読み込むための非同期動作は、以下のようにPromiseオブジェクトにパッケージ化することができる.
// promise.js
var fs = require('fs');
var readFilePromise = function readFilePromise(file) {
return new Promise((resolve, reject) => {
fs.readFile(file, function (err, data) {
if (err) {
reject(err);
}
resolve(file + ': ' + data.toString());
});
});
}
readFilePromise('file1.txt').then(
function (data) {
console.log(data);
}
).catch(function (err) {
// err
});
babel-nodeを使ってpromise.jsファイルを実行して結果を印刷します.file1.txt: file1
ブルーバード上記の自分でPromiseオブジェクトをカプセル化する方法以外に、第三者ライブラリbluebirdを借りることができます.
bluebird以外にもPromiseを実現するための第三のライブラリがあります.例えばq、bluebirdに関するもっと多い比較と紹介はWhat's the difference between Q、Bluebird、and Ayncを参照してもいいです.
上記Promiseオブジェクトを使用して実現された例については、bluebirdを用いて以下のように実現されています.
// bluebird.js
var Promise = require('bluebird');
var readFile = Promise.promisify(require('fs').readFile);
readFile('file1.txt', 'utf8').then(
function (data) {
console.log('file1.txt: ' + data);
}
).catch(function (err) {
// err
});
ブルーバードを使用する前に、インストール依存が必要です.npm i--save bluebirdbabel-nodeを使ってbluebird.jsファイルの印刷結果は以下の通りです.
file1.txt: file1
GeneratorPromiseはCallback Hellの問題を解決できますが、チェーンのコードはまだ直観的ではないようです.
従ってES 6にはGenerator関数が導入され、またジェネレータ関数と呼ばれる.
Generator関数と一般関数の違いは、functionの後ろに星番号を追加したということです.すなわち、function*
例えば、以下のGenerator関数を用いて、ファイルを読み込む例
// generator.js
var fs = require('fs');
function* generator(cb) {
yield fs.readFile('file1.txt', cb);
yield fs.readFile('file2.txt', cb);
yield fs.readFile('file3.txt', cb);
};
var g = generator(function (err, data) {
console.log('file1.txt: ' + data);
});
g.next();
Generator関数は以下の二つの特徴があります.Generator関数を呼び出して返したのはGeneratorオブジェクトですが、コードはyieldで実行を一時停止します.
Generatorオブジェクトのnext()メソッドコードを実行し続けて次のyieldに一時停止します.
上记のように、コードは一回だけnext()メソッドを実行していますので、file 1.txtを読んでから停止します.
したがって、Babel-nodeを使ってgenerator.jsファイルの印刷結果は以下の通りです.
file1.txt: file1
coGenerator関数は目的は良いですが、理解と使用が不便なので、神器coがあります.
これはGenerator関数を自動的に実行するために、開発者がGeneratorオブジェクトを手動で作成する必要がないようにし、next()を呼び出す方法です.
coを使った後に非同期のコードはこのように見えます.
// co.js
var Promise = require('bluebird');
var readFile = Promise.promisify(require('fs').readFile);
var co = require('co');
co(function* () {
var data = yield readFile('file1.txt', 'utf8');
console.log('file1.txt: ' + data);
data = yield readFile('file2.txt', 'utf8');
console.log('file2.txt: ' + data);
data = yield readFile('file3.txt', 'utf8');
console.log('file3.txt: ' + data);
}).catch(function (err) {
// err
});
coを使用する前にインストール依頼が必要です.npm i--save cobabel-nodeでco.jsファイルを実行して印刷します.結果は以下の通りです.
file1.txt: file1
file2.txt: file2
file3.txt: file3
上記の例から、coは以下の2つの特徴があることが分かります.co()はPromiseに戻ります.
coパッケージのGenerator関数の中のyieldの後ろはPromiseでなければなりません.
上記のcoの基本的な使い方以外にも、coを使ってGenerator関数を普通の関数にカプセル化することができます.
// co-wrap.js
var Promise = require('bluebird');
var readFile = Promise.promisify(require('fs').readFile);
var co = require('co');
var fn = co.wrap(function* () {
var data = yield readFile('file1.txt', 'utf8');
console.log('file1.txt: ' + data);
data = yield readFile('file2.txt', 'utf8');
console.log('file2.txt: ' + data);
data = yield readFile('file3.txt', 'utf8');
console.log('file3.txt: ' + data);
});
fn();
babel-nodeでcow-wrap.jsファイルを実行して結果を印刷します.file1.txt: file1
file2.txt: file2
file3.txt: file3
ここを見ていると、coがGeneratorに協力するのは本当に非同期的な開発の「究極」だと思います.また、coのソースコードは200行以上しかありません.中には多くのコメントと空行が含まれています.
async/await
异歩の「究极」に感慨を覚えたばかりだ.coとGeneratorはなぜまだ物语が终わっていないのか?
理由は簡単です.JavaScript言語の原生も同じようなcoを入れてGeneratorの実現に協力しました.async/await
ここのasyncはJavaScriptの最新バージョンの中で非同期のキーワードを実現して前に紹介した第三者の倉庫asyncと混同しないでください.
総じてオリジナルの方がいいですので、co公式ではasync/awaitを使うことを勧めています.
このことが思い出されます.iPhoneの脱獄プラグインの多くは最新バージョンのiOSに組み込まれていますので、脱獄に興味を持つ人が多くなりました.
余談はないですが、そのままオリジナルの異歩「究極の神器」を見てみましょう.
async/awaitを使う前にまずbabelを配置して依存を追加する必要があります.
npm install --save-dev babel-preset-stage-3
ルートディレクトリに追加します.Babelrcファイルの内容は以下の通りです.{
"presets": [
"stage-3"
]
}
async/awaitは最新のJavaScriptバージョンstage-3で導入されたES 6はサポートされていません.続いてJavaScript言語の原生のasync/awaitを使うことができます.
// async/await.js
var Promise = require('bluebird');
var readFile = Promise.promisify(require('fs').readFile);
var fn = async function () {
var data = await readFile('file1.txt', 'utf8');
console.log('file1.txt: ' + data);
data = await readFile('file2.txt', 'utf8');
console.log('file2.txt: ' + data);
data = await readFile('file3.txt', 'utf8');
console.log('file3.txt: ' + data);
};
fn();
上記の例からasync/awaitには以下の2つの特徴があることが分かります.async/awaitと一般関数の使い方はほとんど同じです.
唯一の違いは、functionの前にasyncを加えて関数内のPromiseの前にawaitを加えることです.
結び目
最後にもう一度JavScriptの非同期プログラムの完全な進展過程を振り返ってみます.
callback (async) -> Promsie (bluebird) -> Generator (co) -> async/await (stage-3)
co大神さんの話を聞いて他の案は全部使いません.早くasync/awaitの懐に入れてください.参照