JS非同期あれらの事一(基礎知識)
6216 ワード
JS非同期それらのこと一(基礎知識)JS非同期それらのこと二(分散型イベント)JS非同期それらのこと三(Promise)JS非同期それらのこと四(HTML 5 Web Workers)JS非同期それらのこと五(非同期シナリオローディング)
js事件の概念
非同期コールバック:
まず、jsの2つの方法について説明します.setTimeout()とset Interval()
定義と使用法:
set Interval()方法はsetTimeoutと似ています.関数または計算式は指定された周期(ミリ秒単位)で呼び出されます.
スレッドブロック
JavaScriptエンジンはシングルスレッドで実行されています.ブラウザはいつでも1つのスレッドだけがJavaScriptプログラムを実行しています.
キュー
ブラウザはイベントサイクルのモデルに基づいています.この中には、レンダーなどの複数のタスクキューがあります.タスクの列にはタスクが置かれています.同じソースのタスクは必ず同じタスクの列にあります.ジョブの優先度は、マウスやキーボードがイベントに対する応答の優先度が高く、他のジョブの約3倍です.
私たちがよく使うsetTimeout関数は、本質的にはこのタスクキューにコールバック関数を追加します.JavaScriptエンジンは、タスクキューのタスクの到来をずっと待っています.単一スレッドの関係で、これらのタスクはキューに並べられます.次から次へとエンジンによって処理されます.
キューが空でない場合、エンジンはキューの先からタスクを取り出し、そのタスクが完了するまでは、エンジンを返して次のタスクを実行します.タスクが前のキューに戻らない場合は、他のタスクは実行されません.
非同期関数の種類
非同期IO:
まず、典型的な例を見てみます.
set Timeout、set Intervalはすべてイベント駆動型に基づいています.通常のブラウザはこれに速すぎるスピードをあげません.普通は200回/秒で、効率が低すぎます.もし密集型の演算があったら、ほほほといいます.しかし、node.jsの中にはprocess.nextTick()という強力なものがあります.運行速度は10万回近く/秒です.
node.jsのイベントサイクル分析に基づいて、各サイクルは一回のtickで、毎回のtickの時、v 8エンジンはイベントキューからすべてのイベントを取り出して順次に処理します.もしnextTick事件が発生したら、それをイベントチームの最後に参加して、次のtickが来る時に実行します.結果として、nextTickイベントの実行が遅延された.
nextTickは確かにあるタスクを列の最後に置いています.(arry.push)nodejsはタスクを実行する時に、一度にキューの中のすべてのタスクを取り出して、順次実行します.全部うまくいけば、先ほど取り出したすべてのタスクを削除して、次の実行を待っています.もし途中でエラーが発生したら、完了したタスクとエラーのタスクを削除して、次の実行を待っています.
アプリケーションシーンを見てみます.
非同期異常の特徴
jsの同調非同期特性のため、try catchによってすべての異常を捉えることができませんでした.
オーロラ事件
私たちは一般的に関数名を通して伝達されます.(引用の方式)実行されるオペレーティング関数は、Oneerrorイベントに伝達されます.
JavaScriptの中で最も一般的な反モードのやり方は、リフレクト内部に更にネストバックがあります.
js事件の概念
非同期コールバック:
まず、jsの2つの方法について説明します.setTimeout()とset Interval()
定義と使用法:
setTimeout() 。
構文:setTimeout(callback,time)
calbackが必要です.呼び出す関数の後に実行するJavaScriptコード列.時間が必要です.コードを実行する前に待つミリ秒の数.set Interval()方法はsetTimeoutと似ています.関数または計算式は指定された周期(ミリ秒単位)で呼び出されます.
function timeCount()
{console.log("this is setTimeout");
setTimeout("timeCount()",1000);
}
function timeCount2(){
console.log("this is setInterval");
}
setInterval("timeCount2()",1000);
timeCount();
timeCount2();
例えば上記のコードは1000ミリ秒ごとにタイムスタンプ関数を実行することができますが、後者は周期的に実行されるtimecount関数、SetIntervalは自動的に繰り返され、setTimeoutは繰り返されません.スレッドブロック
JavaScriptエンジンはシングルスレッドで実行されています.ブラウザはいつでも1つのスレッドだけがJavaScriptプログラムを実行しています.
function f() { console.log("hello world");}
var t = new Date(); // 5
while(true) {
if(new Date() - t > 5000) {
break; }
}
setTimeout(f, 1000);
上記のコードを実行すると、全体の運転時間はほぼ6秒以上かかります.シングルスレッドなので、whileサイクルで5秒の時間を消費してから、settimeout関数を実行します.キュー
ブラウザはイベントサイクルのモデルに基づいています.この中には、レンダーなどの複数のタスクキューがあります.タスクの列にはタスクが置かれています.同じソースのタスクは必ず同じタスクの列にあります.ジョブの優先度は、マウスやキーボードがイベントに対する応答の優先度が高く、他のジョブの約3倍です.
私たちがよく使うsetTimeout関数は、本質的にはこのタスクキューにコールバック関数を追加します.JavaScriptエンジンは、タスクキューのタスクの到来をずっと待っています.単一スレッドの関係で、これらのタスクはキューに並べられます.次から次へとエンジンによって処理されます.
キューが空でない場合、エンジンはキューの先からタスクを取り出し、そのタスクが完了するまでは、エンジンを返して次のタスクを実行します.タスクが前のキューに戻らない場合は、他のタスクは実行されません.
非同期関数の種類
非同期IO:
まず、典型的な例を見てみます.
var ajax = new XMLHttpRequest;
ajax.open("GET",url);
ajax.send(null);
ajax.onreadystatechange = function () {
if (request.readyState === 4) {
if (request.status === 200) {
return success(request.responseText);
} else {
return fail(request.status);
}
}
}
非同期時間:set Timeout、set Intervalはすべてイベント駆動型に基づいています.通常のブラウザはこれに速すぎるスピードをあげません.普通は200回/秒で、効率が低すぎます.もし密集型の演算があったら、ほほほといいます.しかし、node.jsの中にはprocess.nextTick()という強力なものがあります.運行速度は10万回近く/秒です.
process.nextTick(callback)
機能:イベントサイクルの次のサイクルでコールバックバック関数を呼び出します.効果は、1つの関数をコード書きに延期する次の同期方法の実行終了時または非同期方法のイベントコールバック関数の実行開始時です.setTimeout(fn,0)関数の機能と似ているが,その効率はかなり高い.node.jsのイベントサイクル分析に基づいて、各サイクルは一回のtickで、毎回のtickの時、v 8エンジンはイベントキューからすべてのイベントを取り出して順次に処理します.もしnextTick事件が発生したら、それをイベントチームの最後に参加して、次のtickが来る時に実行します.結果として、nextTickイベントの実行が遅延された.
nextTickは確かにあるタスクを列の最後に置いています.(arry.push)nodejsはタスクを実行する時に、一度にキューの中のすべてのタスクを取り出して、順次実行します.全部うまくいけば、先ほど取り出したすべてのタスクを削除して、次の実行を待っています.もし途中でエラーが発生したら、完了したタスクとエラーのタスクを削除して、次の実行を待っています.
アプリケーションシーンを見てみます.
var http = require('http');
var wait = function (mils) {
var now = new Date;
while (new Date - now <= mils);
};
function compute() {
// performs complicated calculations continuously
console.log('start computing');
wait(1000);
console.log('working for 1s, nexttick');
process.nextTick(compute);
}
http.createServer(function (req, res) {
console.log('new request');
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World');
}).listen(5000, '127.0.0.1');
compute();
非同期エラー処理非同期異常の特徴
jsの同調非同期特性のため、try catchによってすべての異常を捉えることができませんでした.
try {
process.nextTick(function () {
foo.bar();
});
} catch (err) {
//can not catch it
}
ウェブサービスにとっては、このような希望が強いです.//express
app.get('/index', function (req, res) {
try {
//
} catch (err) {
logger.error(err);
res.statusCode = 500;
return res.json({success: false, message: ' '});
}
});
try catchがすべての異常を捉えることができれば、コードに予期せぬエラーが発生した場合、エラーを記録しながら、友好的に調達者に500のエラーを返します.残念ながら、try catchは非同期の異常を捕まえられません.このように放棄しますか?実はもう一つの方法があります.オーロラ事件
私たちは一般的に関数名を通して伝達されます.(引用の方式)実行されるオペレーティング関数は、Oneerrorイベントに伝達されます.
window.onerror=reportError;
window.onerror=function(){alert('error')}
しかし、イベントがトリガされた時には、エラーメッセージ、エラーページのurlとエラー行番号の3つのデフォルトのパラメータがあることを知らないかもしれません.
window.onerror=testError;
function testError(){
arglen=arguments.length;
var errorMsg=" :"+arglen+" ";
for(var i=0;i<arglen;i++){
errorMsg+="
"+(i+1)+":"+arguments[i];
}
alert(errorMsg);
window.onerror=null;
return true;
}
function test(){
error
}
test()
ネスト型リフレクトの取り外しJavaScriptの中で最も一般的な反モードのやり方は、リフレクト内部に更にネストバックがあります.
function checkPassword(username, passwordGuess, callback) {
var queryStr = 'SELECT * FROM user WHERE username = ?';
db.query(queryStr, username, function (err, result) {
if (err) throw err;
hash(passwordGuess, function(passwordGuessHash) {
callback(passwordGuessHash === result['password_hash']);
});
});
}
ここでは非同期関数checkPasswordを定義しています.他の非同期関数db.queryをトリガします.後者は他の非同期関数hashをトリガする可能性があります.使えます.簡潔で分かりやすいです.しかし、新しい特性を追加しようとすると、毛の中が粗くなり、危険な環境になります.例えば、そのデータベースのエラーを処理します.間違いを捨てたり、記録したりすることではありません.データベースの回数を聞いたり、データベースへのアクセスをブロックしたりします.このような書き方はくどいですが、読み取り可能性が高く、拡張しやすいです.
function checkPassword(username, passwordGuess, callback) {
var passwordHash;
var queryStr = 'SELECT * FROM user WHERE username = ?';
db.query(qyeryStr, username, queryCallback);
function queryCallback(err, result) {
if (err) throw err;
passwordHash = result['password_hash'];
hash(passwordGuess, hashCallback);
}
function hashCallback(passwordGuessHash) {
callback(passwordHash === passwordGuessHash);
}
}
ふだん入れ子を書く時、私達はできるだけ重層の入れ子を避けるべきで、さもなくば中間のあるところは間違いをして、あなたが更に多くの時間を投入してdebugに行くことを招きます.