2

状況は次のとおりです。

Web ベースのチケット アプリケーション、複数のユーザーがいます。

発生する可能性のある問題の 1 つ (置き換えようとしている古いバージョンで発生します) は、user1 がチケットを開いて編集し、保存することです。しかし、彼がそれを編集している間に、user2 もチェックマークを開いて保存しました。user2 が行った変更は、user1 によって失われるか上書きされます。

これを防ぐために、ロック メカニズムを実装しました。それはかなり単純です。

  1. チケットを開くと、PHP スクリプトは既存のロックをチェックします。
  2. 見つからない場合は、ドキュメントをロックして開きます。
  3. JS ではsetTimeout()、XmlHttpRequest を呼び出して 10 分後にチケットのロックを解除します (問題なく動作します)。
  4. unloadウィンドウ/タブを閉じる/離れるときにチケットのロックを解除するイベントも設定しました

問題はステップ 4 にあります:unloadイベント (& it's friend ) は、これを確実beforeunloadに実装するには十分に機能しません(この機能が重大な意味を持つためには、信頼できる必要があります)。多くのブラウザーは常にそれを起動するとは限りません。起動したいとき(戻るボタンを押す、F5を押す、タブを閉じるなど。これはブラウザによって異なります)

私が思いつくことができる唯一の代替手段は、ページがまだ開いていることを伝えるために php スクリプトを呼び出してsetTimeout()使用することです。XmlHttpRequest()この「ハートビート」モニターが失敗した場合、ユーザーがチケットから離れ、ドキュメントのロックを解除したと見なされます。

これは私には恐ろしく非効率的であり、数人のユーザーでもすぐにサーバーへの多くのリクエストにつながります.

これを処理する方法について、より良いアイデアを持っている人はいますか?

IE8+ およびその他の最新のブラウザー (理想的には、Firefox、Webkit、Opera) で動作する必要があります。私は IE6/IE7 を気にしません。私たちの組織はそれらを使用していません)。

4

3 に答える 3

1

XHRを介してハートビートpingを使用するのが最善の方法です。ユースケースによっては、ユーザーがx秒ごとではなくフィールドへの入力を停止した後に送信することもできます。これにより、ページは開いたままになりますが、非アクティブな場合はロックされたままになりません。

ユーザーが入力を停止した後にこれらのXHRを送信する場合は、keydown/up/pressイベントの1つとデバウンス/スロットルスクリプトを使用して、ユーザーが入力を停止したときにのみリクエストを送信します。長い間入力している)。

于 2011-09-23T12:57:46.920 に答える
1

最善の解決策ではないかもしれませんが、調べる価値はあります: websockets .
ページの読み込み時にサーバーとの接続を確立し、接続が失敗した場合 (つまり、クライアントが ping に応答しない場合)、チケットのロックを解除できます。socket.io
のようなものを使用すると、この手順が ie8 でも機能することが保証されます。

  • 主な利点は、 n秒ごとにリクエストを送信するのではなく、サーバーがn秒ごとに ping を送信するため、unload/beforeunloadイベントを気にする必要がないことです。クライアントが ping に応答しない場合は、チケットのロックを解除します。
  • 主な欠点は、すべての Websocket 接続を処理するサーバーが必要なことです。これは、ほぼすべてのサーバー側言語で実行できますが、単純な Web サービスよりも少し難しい場合があります (xhr ポーリングの場合)。
于 2011-09-23T13:22:44.193 に答える
0

ドキュメントのロックを自動的に解除する ajax ハートビートまたはアンロード ハンドラーを実装するのは注意が必要です。

問題は、ターゲットとするすべてのブラウザーで beforeunload をサポートしていても、ブラウザーがクラッシュしたり、ユーザーが眠りに落ちたりした場合に呼び出されない可能性があることです。

webdav の仕組みを見てください。編集を開始する前に明示的にロックを取得してから、明示的にロックを保存して解放します。他のユーザーは誰がロックを取得したかを確認でき、管理者は誤って取り残されたロックを解放できます。

于 2011-09-23T14:37:20.440 に答える