1

JavaScript の際立った機能の 1 つ (または、この件に関する見解によっては不利な点) は、その非同期性です。コード フローがどのように機能するかは理解していますが、非同期コードを「非同期」にする理由については 100% ではありません。

確かに、サーバーへの接続やデータベースへの読み取り/書き込みは非同期アクションです。しかし、通常は非同期で処理されるものはどうでしょうか? コールバックを使用して 1 日中非同期にするコードを書くことができます。

同期の例

var arrayToIterate = [1,2,3,4,5,6,7,8,9, ... ]  
//Say this array length is in the hundreds of millions.

var addArrayContents = function(array) {
    var total = 0;

    for (var i = 0, len = array.length; i <= len; i++) {
        total = total + array[i];
    }

    return total;
};

var arrayTotal = addArrayContents(arrayToIterate);

 

非同期の例

var arrayToIterate = [1,2,3,4,5,6,7,8,9, ... ]  
  //Say this array length is in the hundreds of millions.

var addArrayContents = function(array, callback) {
    
    var iterator = function(total, arIndex, cb) {
        if (arIndex == array.length) {
            return cb(total);
        }

        total = total + array[arIndex];
        arIndex++;

        iterator(total, arIndex, cb)
    };

    iterator(0, 0, callback);
};

addArrayContents(arrayToIterate, function(result){
    console.log(result);
    // Do stuff
});

おわかりのように、どちらの関数も同じことを行います。一方は非同期で、一方はそうではありません。何かを同期的に行うよりも非同期的に行うのに最適な時期を決定する際の経験則はありますか? 上記の例では、同期関数はこれらの数値を加算するときに引っかかりますが、非同期バージョンは実行中にハングしません。

私は非同期性を 100% 理解していないと感じています。関数を調べてコールバックを使用しているかどうかを調べるだけではないようです。

4

1 に答える 1

2

2番目のバージョンは非同期ではありません...ネストされた関数は、それ自体を再帰的に呼び出しているだけです(ところで、大きな配列では悪い考えです)。

非同期にするには、代わりにsetTimeout、計算が後で続行されるようにタイマーを ( で) スケジュールする必要があります。

var index = 0;
var total = 0;
function step() {
    if (index < array.length) {
        total += array[index++];
        setTimeout(step, 0);
    } else {
        callback(total);
    }
}
setTimeout(step, 0);

この場合、関数はすぐに呼び出し元に戻り、計算が完了すると完了コールバックが後で (非同期に) 呼び出されます。

たとえば、内部的に実装する方法の 1 つsetTimeoutは、タイマー イベントのヒープを起動されるのを待機させることです。JS 環境が現在のイベントを完了すると、次に何が生成されるかを確認し、ハンドラーを呼び出すヒープからアイテムを削除します。

タイマーイベントに加えて、マウスイベント、ネットワークイベント、メッセージイベントなどがあることにも注意してください...通常、タイマーイベントには最も低い優先度が与えられるため、他に何もすることがない場合にのみコードが呼び出されます(これが、タイミングが正確ではなく、指定された遅延は最小の遅延です)。

通常、ブラウザーに他のイベントがない場合でも、JS は、タイマー ハンドラーを呼び出す前に、必要に応じて最初に DOM の再描画を行います (そのため、setTimeout(f, 0).

于 2013-05-17T21:01:00.457 に答える