現在でもコンポーネント開発は依然として非常に人気があり、その利点は非常に顕著です。最近、コンポーネントを開発しているときに、非常に興味深いバグに遭遇しました。 。 。
バグの背景
最近コンポーネントを開発していて、ようやく完成してテストしました。そしたら、テストでこのバグについて言及されましたorz...
コンポーネントなのでどこでも再利用できるのが最大の利点ですが、ページで複数のコンポーネントを使用している場合のみ。最後のコンポーネントが有効になると、このコンポーネントは意味を持ちません。 。 。
バグ原因検索
このコンポーネントの初期データソースのインターフェースは固定されています。つまり、ページ内のすべてのコンポーネントは初期化時に同じリクエストを発行します。コールバック関数はウィンドウにバインドされた関数ですが、ページ内にウィンドウは 1 つしかないため、コールバック処理中、処理対象のコンポーネント内の対応するデータは最後のコンポーネントのみを指します。その結果、複数の同一のコンポーネントが同じページに配置され、データを取得した後、最後のコンポーネントのみが正常にレンダリングされます。
バグ解決策のアイデア
最も重要なことは、コールバック内のコンポーネント データの処理が最後のリクエストのみをポイントしないように、各リクエストのコールバックを保存することです。第 2 に、これは同じリクエストであるため、当然のことながら、2 回以上発行されることは望ましくありません。つまり、ページによって発行されるすべてのリクエストは一意です。
バグ解決策
サブスクライバーモードでカスタムイベントを発行することを考えました。各リクエストが送信される前に、同じモジュールが以前に送信されたかどうかを判断します。そうでない場合は、キャッシュコールバックが行われます。同じリクエストが発行された場合は、発行されたリクエストが完了したかどうかを確認し、完了していない場合は、コールバックをキャッシュし続け、リクエストが発行されて完了した場合は、コールバックが直接処理されます。初めてリクエストが返された後、ブロードキャストが発行され、以前にキャッシュされたすべてのコールバックが実行されます。
カスタム イベントの詳細
コールバック関数にちなんで名付けられた n 個のイベント オブジェクトを含むモジュールを定義します。各オブジェクトが初期化されると、その状態、対応するコールバック配列、およびリクエストの戻り値が定義されます。このモジュールが呼び出されるたびに、まず対応する cbName が初期化されているかどうかを確認し、次にその状態を確認します。状態に応じて対応する操作を実行し、状態の値を変更します。状態には、init、loading、loaded の 3 つの値があります。つまり、初期化、要求、完了の要求です。対応するコールバックは、リクエストが完了した場合にのみ実行できます。詳細は次のとおりです:
define('wq.getData', function (require, exports, module) { var ls = require('loadJs'); var cache = {}; cache.init = function(cb,cbName,url){ if(!cache[cbName]){ cache[cbName] = {}; cache[cbName].state = 'init'; cache[cbName].cbs = []; cache[cbName].data = []; } cache.on(cb,cbName,url); } cache.on = function(cb,cbName,url){ if(cache[cbName].state == 'loaded'){ cb(cache[cbName].data) }else if(cache[cbName].state == 'loading'){ cache[cbName].cbs.push(cb) }else if(cache[cbName].state == 'init'){ cache[cbName].cbs.push(cb); cache[cbName].state = 'loading'; cache.fetch(cb,cbName,url); } } cache.broadcast = function(cbName){ cache[cbName].cbs.forEach(function(cb){ cb(cache[cbName].data) }); } cache.checkLoaded = function(cbName){ if(cache[cbName].data[0]){ cache[cbName].state = 'loaded'; cache.broadcast(cbName); } } cache.fetch = function(cb,cbName,url){ ls.loadScript({ url: url, charset: 'utf-8', handleError:function(func, args, context,errorObj){ console.log(_errlogText + context); cache[cbName].data[0] = {}; cache.checkLoaded(cbName); } }); if(window.cbName) return; window[cbName] = function(json){ cache[cbName].data[0] = json; cache.checkLoaded(cbName); } } exports.getData = function(cb,cbName,url){ cache.init(cb,cbName,url); } })
問題を完全に解決し、各コールバックが見逃されたり上書きされたりすることはありません...
拡張アイデア
このモジュールは、ページ内で同じリクエストを処理するために汎用的に使用できます。また、特定のコールバックを実行する前に 3 つ以上のリクエストを完了する必要がある状況を処理するように拡張することもできます。プロミスの場合と同様です。このとき、data[0]にはインターフェイスに対応する固定データが含まれ、data[2]にはインターフェイスに対応する固定データが含まれる、というように規定することができます。ただし、これには、コールバックを実行する前に、各項目が true になるまでトラバースする必要があります。また、対応関係が混乱しやすいので、さらに拡張する場合はPromiseを使って対応した方が良いでしょう。 。 。
以上がカスタムイベントを正常に解決し、リクエストが繰り返されるバグを解決しましたの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。