手足を出る42行のコード

大規模なプロジェクトの設計には時間がかかり、書くのに時間がかかり、時には拷問を受け、最終的にはgivesめます。 別の「ホットデバッグ」が1か月経ち、その後、re敬の念の沈黙があります。 お客様からは何も聞きません。 そして彼があなたの労働のおかげで壊れたからではありません。 彼は電話代を支払っておらず、インターネットは長い間切断されています。いいえ)すべてが彼の通常モードで機能しているということです。



しかし、ある日... そう! 「 プログラムが機能しません 」という石鹸((C)bash)が届き、電話が赤くなり、弁護士は「保証サービス」セクションで投げたものを神経質に読み直します。



まさにこの状況は私たちにありました。 私たちはかなり重要なプロジェクトを行いました。その本質は次のように説明できます(もちろん)。異なるコンテンツ(クライアントベース、マーケティングベース、コミュニケーションベースなど)とそれを提示するさまざまな方法(ウィジェット、ポップアップ、モーダルなど)があります。 。)。 つまり、お客様の開発者がコントローラーを作成できるように、プラットフォーム(データアクセスAPI、視覚化、エコシステム全体、私はそれが何を意味するのかわかりませんが、それは本当にクールに聞こえます)から準備されましたデータを指定し、ファイルを指定した場所に単に「配置」します。その後、ある種のトリッキーなインデックスの現在の引用符のリストで新しいウィジェットがどのように表示されるかがわかります。



そして、私が言ったように、すべてがうまくいった。 私たちはいくつかの「マスター」クラスを費やし、皆が見せて、彼らは皆、ビールを飲み、回転させました。 すでに私たちなしで。



すべてが壊れるまで。 そうです:「すべて」と「壊れた」。 ある時点で、アプリケーションは単にハングし始めました。 はい。ブラウザのタブを閉じることができません。 少し経験のあるWeb開発者はすぐに言うでしょう-あなたのサイクルはどこかで子供たちを捕まえました。 そして、それは正しいでしょう。



しかし、非常に42行のコードに進む前に、あらゆる種類のグッズが内部にあるアプリケーションがある場合、それらの間の通信を整理する最良の方法は内部イベントを使用することであることを思い出します。 そして、プロジェクトの引き渡し時点で約100があり、問題が始まると、その数はさらに数十個増えました。



そして、あなたが既に推測したように、イベントコントローラーは「スタック」します。 指で:イベントAは、イベントBをトリガーし、イベントB-イベントCをトリガーし、次に、イベントAをトリガーします。Ta-da-m、ループに会います!



イベントハンドラはとてつもなくシンプルで、44行のコードのファイルの中に集まっていました。 しかし、彼は非常に関連性のある小さなものを作る方法を知りませんでした-彼がサイクルにいたかどうかを確認するために。



私はあまり考える必要がなく、解決策はすぐに見つかりました。 良いか悪いかはあなた次第です。 主なアイデアのみを説明します。



誰がイベントのチェーンを引き起こしたかを確認する唯一の方法(この例では、A、B、およびCを見つける)は、スタックを確認することです。 スタックを取得するには、エラーをスローするだけです。



問題は残っています-以前に起動されたイベントのチェーン全体を認識するのに役立つ何かがスタック上にあるはずなので、イベントが呼び出された場所を「マーク」する方法は? この問題の解決策の1つは、ラッパー関数という名前で、その名前には以前のイベントに関するすべての情報が保存されます。 何も分からなかった? 私は書き、読み直し、そしてまた理解しませんでした。 コードが見やすくなりました。



そのため、これを行うと(イベントAがBを呼び出し、BがCを呼び出し、Cが再びAを呼び出します):



var safeevents = new SafeEvents(); safeevents.bind('A', function () { safeevents.trigger('B'); }); safeevents.bind('B', function () { safeevents.trigger('C'); }); safeevents.bind('C', function () { safeevents.trigger('A'); }); safeevents.trigger('A');
      
      





この場合、アプリケーションは手足に入らず、コンソールに例外をスローします。「Uncaught Error:Event [A] called。self。 フルチェーン:A、B、C。」 利益 これで、開発者は問題が何であるかを理解するために3つの追加の休憩に行く必要がなくなりました-すべてはコンソールのメッセージから見ることができます。



非同期呼び出しでは、少し注意が必要です。 残念ながら、追加のアクションを実行する必要があります。 しかし、それは非常に小さいため、大きな問題になることはほとんどありません。



  var safeevents = new SafeEvents(); safeevents.bind('A', function () { safeevents.trigger('B'); }); safeevents.bind('B', function () { safeevents.trigger('C'); }); safeevents.bind('C', function () { /* * Use method "safely" to wrap your async methods and create safe callback. */ setTimeout(safeevents.safely(function () { safeevents.trigger('A'); }), 10); }); safeevents.trigger('A');
      
      





タイマーのコールバック関数に注意してください。 非同期呼び出しで以前のイベントのデータを渡すための「ラッパー」を追加しています。 そして再びコンソールで、「Uncaught Error:Event [A] called。self。」と表示されます。 フルチェーン:A、B、C。」



もちろん、常にそれを受け取って、例外を大胆にスローする必要はありません。 ログのどこにデータを書き込むか、管理者に通知を送信するかを静かに伝える方がはるかに優れています。 「ループ」の場合にハンドラーを配置し、必要なすべてのデータを取得できる理由。



  var safeevents = new SafeEvents(); safeevents.bind('A', function () { safeevents.trigger('B'); }); safeevents.bind('B', function () { safeevents.trigger('C'); }); safeevents.bind('C', function () { safeevents.trigger('A'); }); safeevents.bind(safeevents.onloop, function (e, chain, last_event, stack) { console.log('Error message: ' + e); console.log('Full chain of events: ' + chain.join(', ')); console.log('Last event (generated loop): ' + last_event); console.log('Error stack: ' + stack); }); safeevents.trigger('A');
      
      





これでアプリケーションはまったく中断しませんが、サイクルは正常に防止されます。



一般に、最も単純なイベントハンドラを書き直し、さらに42行のコードを受け取ったことで、イベントループに関する非常にまれではあるがかなり汚い問題を解決しました。 誰が知っているか(私は知りません)、多分あなたにとって役に立つでしょう。 それだけです。



あなたの家への幸福、善、そして電気。



All Articles