none
javascript で location.href の書換えと submit RRS feed

  • 質問


  • ※ WinXP/IE6 や Win7/IE9などで確認(おそらくOSやブラウザに依存しないと思いますが)。

    JavaScript の関数内で、フレームのurlを書き換えてブランク画面にする処理を実行後、直ぐに該当するフレームをターゲットにしたsubmitを実行します(実際の動作はファイルアップロード)。
    submitに時間がかかる場合、ブランク画面となって欲しいのですが、ブランク画面とならずsubmitからのレスポンスがあるまで実行前の内容が表示されたままです。
    対処としては、frame1 の内容を直接書き換える等で可能かと思いますが、

    (質問)
    location.href の書換え後 submit による location の書換え(?)により、「location.href の書換えによる動作」が行われないという、javasciprt か ブラウザの仕様によるものでしょうか?


    ※ 別のフォーラムで「location.href の書換えによって、ナビゲーションが発生しますが、その処理は非同期なので、当然」との返信をいただきました。
      非同期の問題ではないとの認識がありましたので、また、こちらのフォーラムの方が良いとの、ご意見をいただきましたので、再質問をしています。


    ---処理イメージ---

    function f1() {
      frame1.location.href = "about:blank";
      form1.submit();
    }
    ---html---
    <form name="p1" enctype="multipart/form-data" method="post" action="cgi" target="frame1">
    <input type="file" name="f1">
    </form>
    <iframe name="frame1" target="frame1" src="~~"></iframe>

     

    2013年7月23日 10:49

回答

  • 関数の終了を待つという仮説への反論として非同期に実行される例を挙げただけです。同期実行される説明として引用したわけではありません。
    2013年7月24日 1:25
  • ブラウザのユーザーインターフェース周りの処理と JavaScript が同じシングルスレッドで動作している事により、JavaScript の処理が終わってからしか描画イベントが発生しないので、意図的に setTimeout 関数などでブラウザの描画イベントを発生させる必要がある。

    と、いう事で OK ?

    2013年7月24日 6:41
  • >  と、いう事で OK ?
     
    いや、その認識を踏まえたうえの話をずっとしているのだと思っています。
     
    「javasciprt か ブラウザの仕様によるものでしょうか?」   

    この問題の解決には、次が重要だと考えています。

    ・submit()がGUI処理と同期なのか非同期なのか
    ・location.hrefがGUI処理と
    同期なのか非同期なのか
    2013年7月24日 8:37
  • その質問文の意味が不明なんですけど。

    javascriptの仕様とか言ってるのは、javascriptが何で出てくるのかわからない、javascriptの言語仕様は関係ないし、location.hrefへの代入操作の仕様とかという意味ですか?

    ブラウザの仕様というのは、ブラウザの実装という意味ですか?

    要するに、仕様か、実装か、という質問ですか?

    そういう意味なら(´・ω・`)さんが先に言ってるようにnot specifiedで、後者でしょう。と、いう事で OK ?



    2013年7月24日 8:48
  • 返信いただいた方々、ありがとうございます。

    調査していく中で確認できた事実:

    function f1() {
      frame1.location.href = "a.html";
      frame1.location.href = "b.html";
      frame1.location.href = "c.html";
    }

    こんなことを実行してみると(IE9の[ツール]-[開発者ツール]-[ネットワーク]で確認したところ)
    a.html のリクエストが発生 => ただし、リクエストは[保留]
    b.html のリクエストが発生 => a.html のリクエストは[中断]、b.html のリクエストは[保留]
    c.html のリクエストが発生 => b.html のリクエストは[中断]、最終的に、c.html が画面に表示される。

    ※ c.html に対してのリクエストだけかと思っていたが、ちょっとビックリ!
    ※ Chrome だと c.html だけしか実行されない(ただし、ツールの表示だけでそのように見せているだけかも知れませんが...)。

    想定される動作:
    通信などの処理(location書換え)は直ぐに実行される/実行しようとする。(submit実行直後の[保留]状態となっていたので、おそらく同様と思われる)
    画面表示は処理が完了後に最終状態のものだけが表示される。

    これだけでは、同期・非同期などは厳密にはわかりませんが、以降も、事実か想定の情報がわかっていくことがあっても、「javasciprt か ブラウザの仕様によるものでしょうか?」は、わからないものと判断します。

    質問そのものが、明確ではなく、ご迷惑をおかけしましたが、ひとまず、質問した者としてはクローズとさせていただきます。

    2013年7月24日 12:23

すべての返信

  • ※ 別のフォーラムで「location.href の書換えによって、ナビゲーションが発生しますが、その処理は非同期なので、当然」との返信をいただきました。
      非同期の問題ではないとの認識がありましたので、また、こちらのフォーラムの方が良いとの、ご意見をいただきましたので、再質問をしています。
    「非同期の問題ではない」というのはどういう意味でしょうか? 同期処理が行われているとお考えでしょうか? もし href に指定したURLがhttpであれば、ネットワークから取得後、表示完了(onloadなども実行完了)後に次の行 form1.submit() に進むとお考えなのでしょうか?
    2013年7月23日 12:17
  • ※ 別のフォーラムで「location.href の書換えによって、ナビゲーションが発生しますが、その処理は非同期なので、当然」との返信をいただきました。
      非同期の問題ではないとの認識がありましたので、また、こちらのフォーラムの方が良いとの、ご意見をいただきましたので、再質問をしています。

    「非同期の問題ではない」というのはどういう意味でしょうか? 同期処理が行われているとお考えでしょうか? もし href に指定したURLがhttpであれば、ネットワークから取得後、表示完了(onloadなども実行完了)後に次の行 form1.submit() に進むとお考えなのでしょうか?

    同期や非同期の話ではなく、それ以前の仕様の話かと考えております。

    記載した JavaScript の関数では、href の書換え後、直ぐに、書き換えた フレームを TARGET にした submit を実行しており、そもそも、href の書換えが、無かったことにされているのではないかとの想定をしております。

    そのように考える理由は、JavaScript での操作が完了した後(ブラウザに制御が戻ってから)にブラウザが描画処理を開始するとに認識があります。そのため、描画する必要が無い書換えを無かったことにしているのでは?と考えています。

    ※ 念のため、明日にでも、"about:blank"以外の有効のアドレスで通信が発生するか確認しておきます。

    2013年7月23日 12:39
  • ちょっと別の話題になってしまいますが、 IMG要素のonloadイベントについて という記事を書いたことがあります。
    img.srcの設定後にimg.onloadを設定するとonloadイベントが発生しないことがあります。これはバグでもなんでもなくonloadイベントの設定前にimg.srcの読み込みが完了してしまっていてonloadイベントは不要と判断されてしまう動作です。

    これと同じことが言えるのではないでしょうか? ページ遷移は非同期に行われるものであり、JavaScriptの関数終了後に行われるわけではない、と。

    • 回答の候補に設定 佐祐理 2013年7月24日 13:22
    2013年7月23日 12:55
  • 画面見えの話題をしているのだと思いました。
     
    基本的にGUIフレームワークの制御は1スレッドで同期的に行われるものらしいですね。
    # 外していたらすみませんが、某書の9章などが参考になりました。

     
    javasciprt か ブラウザの仕様によるものでしょうか?
     
    そういった”プロパティ同士”の処理順の記述はHTML仕様MSDNには見つけられません(し、期待しない方がよいかと)でした。
    該当部に限らず、各種の他の仕様調整の結果、該当部の動作は、結果的に見たままの動作しているのだと思っております。
    2013年7月23日 14:28
  • たとえて言うと、VBAのDoEventsが必要なのでは。

    function f1() {
      frame1.location.href = "about:blank";
      form1.submit();
    }

    でなく、

    function f1() {
      frame1.location.href = "about:blank";
      setTimeout("f2()",100);
    }

    function f2() {
       form1.submit();
    }

    2013年7月23日 16:01
  • 提示していただいた内容ですと画像が表示されると思いますが、今回の場合は、submit の実行待ちの間は ブランク 画面になって欲しいのですが、そうはなりません。よって、今回の質問の現象とは一致しないと思います。
    2013年7月23日 23:29
  • たとえて言うと、VBAのDoEventsが必要なのでは。

    function f1() {
      frame1.location.href = "about:blank";
      form1.submit();
    }

    でなく、

    function f1() {
      frame1.location.href = "about:blank";
      setTimeout("f2()",100);
    }

    function f2() {
       form1.submit();
    }

    提示ありがとうございます。

    こちらでも、ブラウザに一度制御を戻す、この方法で、画面がブランクになることは確認できています。

    その他、frame1.document.body.innerText = "" など、直接表示内容を消去するなどでも実現はできています。

    質問の意図としては「javasciprt か ブラウザの仕様によるものでしょうか?」、また、同期や非同期に動作によるものか?などの、できれば技術的な情報がわかればと質問させていただきました。

    2013年7月23日 23:47
  • URL が書き換わったか判定すればいいのでは、、、
    と試しに IE10 の URL に about:blank と入力した後に javascript:alert(location.href) とした場合に拾えない事から、IE の問題なのかもしれません。
    ちなみに chrome では取得出来ましたので期待通りの動きをするかもです。
    2013年7月24日 1:00
  • IE8 の 場合は、 about:Tabs は拾えますね。

    これに変えた場合の動きはどうでしょうか。

    2013年7月24日 1:05
  • 関数の終了を待つという仮説への反論として非同期に実行される例を挙げただけです。同期実行される説明として引用したわけではありません。
    2013年7月24日 1:25
  • スクリプト操作した内容を反映させるには、一旦ブラウザに制御を戻さないと反映されない。
     
    確かに、このような当然のことは仕様のどこかに記載されているように思えますね。
    PeekMessage()等の非同期向けAPIをのぞいて
    JavaScript処理というのはGUIスレッドと同期して処理が行われるのは仕様で定義されているのではないか?
    ただ、フレームをまたがった場合は裏で通信がされて反映されても良さそうだし、そもそもブラウザに制御を戻した後であるため、うまく表示される可能性があり、その部分を話題にしている。
     
    と解釈いたしました。
     
    仕様に無いんでしたっけ?
     
    参考程度に今思ったことを書かせていただきますと、
    ちょうど話に出た「画像」を例にすると、これをGUIを設計する際は、Proxyパターンを用いて枠だけを表示しておき、別途裏で通信すると都合がよさそうに思えます。実際そのように動作しているように見える事象がある。
    同じように「ウィンドウ」についても、GUIを設計する際は、Proxyパターンを用いて枠だけを表示しておき、別途裏で通信すると都合がよさそうに思えます。
     
    一方、submit()の方は、同期的に動作するイメージをしています。
    上記の想定のとおり裏でとってきた可能性の高いと考えるabout:blankは反映を待ち受けている状態になっているのかもしれませんね。
     

    フレームを管理するWindowProxyオブジェクトの仕様を確認してみても、どうやら変数空間の単位であって表示の同期性については触れられていないようです。 http://d.hatena.ne.jp/cou929_la/20110310/1299767973

    2013年7月24日 3:50
  • ユーザーの体感速度を高めるためのJavaScriptチューニング(後編) | HTML5Experts.jp http://html5experts.jp/yoshikawa_t/1016/

    ここに書かれているような方法

    function f1() {
      frame1.location.href = "about:blank";
      setTimeout(function(){
        form1.submit();
      }, 0);
    }

    で、良いような・・・

    2013年7月24日 4:09
  •   frame1.location.href = "about:blank";
      setTimeout("f2()",100);

    試した感じでは、urlによって時間は変わるようです。about:blankなら短くてもよいでしょうが、それでもシステム負荷などによっては足りないことがないとはいえないでしょう。非同期とはそういうものです。

    一般のurlでは、

    URL が書き換わったか判定すればいいのでは、、、
    と試しに IE10 の URL に about:blank と入力した後に javascript:alert(location.href) とした場合に拾えない事から、IE の問題なのかもしれません。

    そういう方法で、待ち合わせをすれば、同期に近くなるでしょうね。

    2013年7月24日 4:45
  • ブラウザのユーザーインターフェース周りの処理と JavaScript が同じシングルスレッドで動作している事により、JavaScript の処理が終わってからしか描画イベントが発生しないので、意図的に setTimeout 関数などでブラウザの描画イベントを発生させる必要がある。

    と、いう事で OK ?

    2013年7月24日 6:41
  • >  と、いう事で OK ?
     
    いや、その認識を踏まえたうえの話をずっとしているのだと思っています。
     
    「javasciprt か ブラウザの仕様によるものでしょうか?」   

    この問題の解決には、次が重要だと考えています。

    ・submit()がGUI処理と同期なのか非同期なのか
    ・location.hrefがGUI処理と
    同期なのか非同期なのか
    2013年7月24日 8:37
  • その質問文の意味が不明なんですけど。

    javascriptの仕様とか言ってるのは、javascriptが何で出てくるのかわからない、javascriptの言語仕様は関係ないし、location.hrefへの代入操作の仕様とかという意味ですか?

    ブラウザの仕様というのは、ブラウザの実装という意味ですか?

    要するに、仕様か、実装か、という質問ですか?

    そういう意味なら(´・ω・`)さんが先に言ってるようにnot specifiedで、後者でしょう。と、いう事で OK ?



    2013年7月24日 8:48
  • 返信いただいた方々、ありがとうございます。

    調査していく中で確認できた事実:

    function f1() {
      frame1.location.href = "a.html";
      frame1.location.href = "b.html";
      frame1.location.href = "c.html";
    }

    こんなことを実行してみると(IE9の[ツール]-[開発者ツール]-[ネットワーク]で確認したところ)
    a.html のリクエストが発生 => ただし、リクエストは[保留]
    b.html のリクエストが発生 => a.html のリクエストは[中断]、b.html のリクエストは[保留]
    c.html のリクエストが発生 => b.html のリクエストは[中断]、最終的に、c.html が画面に表示される。

    ※ c.html に対してのリクエストだけかと思っていたが、ちょっとビックリ!
    ※ Chrome だと c.html だけしか実行されない(ただし、ツールの表示だけでそのように見せているだけかも知れませんが...)。

    想定される動作:
    通信などの処理(location書換え)は直ぐに実行される/実行しようとする。(submit実行直後の[保留]状態となっていたので、おそらく同様と思われる)
    画面表示は処理が完了後に最終状態のものだけが表示される。

    これだけでは、同期・非同期などは厳密にはわかりませんが、以降も、事実か想定の情報がわかっていくことがあっても、「javasciprt か ブラウザの仕様によるものでしょうか?」は、わからないものと判断します。

    質問そのものが、明確ではなく、ご迷惑をおかけしましたが、ひとまず、質問した者としてはクローズとさせていただきます。

    2013年7月24日 12:23
  • a.html のリクエストが発生 => ただし、リクエストは[保留]
    b.html のリクエストが発生 => a.html のリクエストは[中断]、b.html のリクエストは[保留]
    c.html のリクエストが発生 => b.html のリクエストは[中断]、最終的に、c.html が画面に表示される。

    これだけで、十分、非同期とわかりますけどね。

    2013年7月24日 12:41
  • ところで一般的には、ページ遷移はせずDOM操作によって必要な画面切り替えを行い、それと並行してxhrを使用してバックグラウンドでアップロードなどの処理を行うことではないでしょうか。

    # なので、location.href書き換えの挙動について、あまり興味の対象にならないかなと。

    2013年7月24日 13:27
  • 一般的には、iframeのdomはセキュリティで触れないこともあるので、

    2つのiframeを交互にdisplay:noneで切り替えて、targetしますね。

    相手がシングルでぐずぐずしてるなら、こっちで多重化しちゃう。


    2013年7月24日 13:56
  • 更新前の書き込みではセキュリティ理由が書かれてなかったので意図が読み取れませんでしたが、iframeのことでしたか。
    # 最初クロスオリジンの制限かと思いました。

    DOM操作で描画を行うのであれば、そもそもiframeも不要かと…。iframeで新たなコンテンツをリクエストしなければ「相手がシングルでぐずぐず」も関係ないですし。

    2013年7月24日 22:43
  • 今なら、X-FRAME-OPTIONS、X-XSS-Protection、X-Content-Type-Option

    辺りを利用しても問題にならないようなページ作りにするべきでしょうね…

    2013年7月25日 0:34