1

ユーザーがログインするためのポップアップ ウィンドウを必要とする FSSO API をまとめています。ポップアップでは、次の 2 つのタスクを実行します。

  1. サービスを呼び出してプロファイル値を設定し、イベント タイプ (ログインまたは登録) に基づいてユーザーをリダイレクトするページを設定します。

  2. ユーザーを親ウィンドウのリダイレクト ページにリダイレクトし、FSSO ポップアップを閉じます。

コード:

$(document).ready(function() {
            var nextPage = "index.html",
            storage = window.opener.sessionStorage;

            function setStorage(callback){
                $.ajax({
                    type: "GET",
                    cache: false,
                    dataType: "json",
                    url: "https://someserviceURL/service/profile",
                    success: function(objJSON){
                        //storage.op is set on the parent page when login or reg link is clicked
                        if (storage.op == "login") {
                            storage.firstname = objJSON.firstName;
                            storage.lastname = objJSON.lastName;
                            storage.setItem('loggedIn',JSON.stringify(true));   //Some browsers don't support booleans in sessionStorage
                            nextPage = "dashboard.html";
                        }
                        else if (storage.op == "register") {
                            storage.firstname = objJSON.firstName;
                            storage.lastname = objJSON.lastName;
                            storage.setItem('loggedIn',JSON.stringify(true));
                            nextPage = "options.html";
                        }
                    },
                    error: function( jqXHR,  textStatus,  errorThrown){
                        //display error message
                    }
                });

                callback();
            }

            setStorage(function(){
                if (typeof window.opener != "undefined" && window.opener != null){
                    setTimeout(function(){
                        window.opener.location.href = nextPage;
                        window.close();
                    },3000);
                }
            });

        });

問題: タイムアウトを 3000 未満に設定すると、sessionStorage の値を設定する前にウィンドウが閉じているように見えます。任意の時間ではなく、設定されている値に応じてウィンドウを閉じたいだけです。通過。タイムアウトを 0 に設定するトリックを試しましたが、うまくいきませんでした。また、タイムアウトなしでコールバックだけを試しました。

このようなタイミングの問題を処理するためのベスト プラクティスをここで探しています。:)

4

2 に答える 2

1

成功関数の最後のアクションとしてコールバックを呼び出す必要があります。

.
.
.
else if (storage.op == "register") {
   storage.firstname = objJSON.firstName;
   storage.lastname = objJSON.lastName;
   storage.setItem('loggedIn',JSON.stringify(true));
   nextPage = "options.html";
 }

 callback();  // execute your callback to the window closer here.

},
error: function( jqXHR,  textStatus,  errorThrown){
      //display error message
                }
      });
      }
于 2013-08-21T23:12:54.483 に答える
1

への呼び出し$.ajax()は非同期です。つまり、スクリプトの残りの部分は、呼び出しが完了して成功ハンドラーまたはエラー ハンドラーをトリガーするのを待たずに、呼び出しが行われた直後に引き続き実行されます。

これは、呼び出された関数callbackが成功ハンドラーの前に実行されていることを意味します。通常、Web サービスは 3000 ミリ秒のタイムアウトで意図したとおりに動作する可能性があります。これは、Web サービスの完了にかかる時間がこれよりも短いことが多いためです。このような場合、コールバックが最初に実行されます。おっしゃったように、これはイベントの順序を制御するための信頼できる方法ではありません。

1 つの解決策は、次のように完全なハンドラーの一部としてコールバックを実行することです。

$(document).ready(function() {
        var nextPage = "index.html",
        storage = window.opener.sessionStorage;

        function setStorage(callback){
            $.ajax({
                type: "GET",
                cache: false,
                dataType: "json",
                url: "https://someserviceURL/service/profile",
                success: function(objJSON){
                    //storage.op is set on the parent page when login or reg link is clicked
                    if (storage.op == "login") {
                        storage.firstname = objJSON.firstName;
                        storage.lastname = objJSON.lastName;
                        storage.setItem('loggedIn',JSON.stringify(true));   //Some browsers don't support booleans in sessionStorage
                        nextPage = "dashboard.html";
                    }
                    else if (storage.op == "register") {
                        storage.firstname = objJSON.firstName;
                        storage.lastname = objJSON.lastName;
                        storage.setItem('loggedIn',JSON.stringify(true));
                        nextPage = "options.html";
                    }
                },
                error: function( jqXHR,  textStatus,  errorThrown){
                    //display error message
                },
                complete: function( jqXHR,  textStatus){
                    callback();
                }
            });
        }

        setStorage(function(){
            if (typeof window.opener != "undefined" && window.opener != null){
                    window.opener.location.href = nextPage;
                    window.close();
            }
        });
    });

または、返された引数を気にしない場合は、 にcallback直接渡すことができますcomplete。complete は成功条件とエラー条件の両方で実行されることに注意してください。そのため、成功ハンドラーでのみコールバックを呼び出し、エラーがある場合は別のことを行うことができます。

于 2013-08-21T23:19:56.267 に答える