2016-05-10 2 views
2

私はjavascriptを初めて使用しています。前の行が終了する前に実行していたコード行に問題があります。私が理解していることから、最後の行が前の行が終了するのを待つコールバック関数を作成する必要があります。私のプログラムはユーザーの入力を受け取り、非同期の '投稿'を使ってそれをウェブサイトに送り、メッセージが返されます。私は一緒に2つのコードに次の行を持っていたとき、私の元の問題が発生しました:非同期の「ポスト」コールバック関数の問題

req.send(JSON.stringify(payload)) 
    event.preventDefault(); 

でpreventDefault()仕上げに送信()関数を待っていません。私はコールバック関数を実装しようとしましたが、私もそれに問題があります。

function sendReq(callback){ 
     req.send(JSON.stringify(payload), function(){ 
      callback(); 
     }); 
    } 
    sendReq(function(){ 
     event.preventDefault(); 
    }); 

ご意見をいただければ幸いです。ここに私のコード全体が役立ちます。

var apiKey = "appid=fa7d80c48643dfadde2cced1b1be6ca1"; 
    document.addEventListener('DOMContentLoaded', bindButtons); 
    function bindButtons(){ 
     document.getElementById('dataSubmit').addEventListener('click', function(event){ 
      var req = new XMLHttpRequest(); 
      var payload = {longUrl:null}; 
      payload.longUrl = document.getElementById('inputData').value; 
      req.open('POST', 'http://httpbin.org/post&' + apiKey, true); 
      req.setRequestHeader('Content-Type', 'application/json'); 

      var response = JSON.parse(req.responseText); 
      req.addEventListener('load',function(){ 
       if(req.status >= 200 && req.status < 400){ 
        document.getElementById('outputData').textContent = response.longUrl; 
       } 
       else 
        console.log("Error in network request"); 
      }); 
      function sendReq(callback){ 
       req.send(JSON.stringify(payload), function(){ 
        callback(); 
       }); 
      } 
      sendReq(function(){ 
       event.preventDefault(); 
      }); 
     }); 
    } 
+1

'event.preventDefault()'は、デフォルトのハンドラが同期的に呼び出されるため、同期的に呼び出される必要があります。デフォルトハンドラをオーバーライドしようとしている場合は、常にそれを呼び出すでしょう。要求が完了するまで遅延させる目的は何ですか? – trex005

+0

私が受け取っているエラーは次のとおりです: 'VM53:1 Uncaught SyntaxError:JSON入力の予期しない終了 ' – zdevita

+0

私は応答メッセージを受信しません。講師から、send()関数の実行が完了する前に 'event.preventDefault();'が実行されていることが教えられました – zdevita

答えて

2

コールバックの仕組みを誤解しています。あなたのコードは常に(例えば、「DOMContentLoaded」としてイベントに応じて動作します: - :recurial.comからこの記事をチェックアウトによる"Run-to-completion" semanticsと呼ばれるものにUnderstanding callback functions in Javascript

あなたは[*] JavaScriptで「待つ」ことができません、 "click"、またはXHRの "load")、現在実行中のコードが終了するまで(通常は最も外側の関数からイベントハンドラによって)イベントが処理され、他のイベントハンドラは処理されません。

長時間実行されるJSコードによってWebページがフリーズするため、最初に非同期要求を書き込むようになったため - 同期XHRによって、コードがサーバーからの応答を待つ間にページがフリーズする。

フリーズを避けるために、コードを一連のコールバックとして構造化することができます。非同期リクエストを開始した後は、現在の関数から戻り、応答があったときにシステムにコールバックさせます。あなたが応答を使用できる唯一の瞬間は、コールバックの非常に明確な定義によって、コールバックにあります。

あなたのケースでは、応答が利用可能であることを示すコールバックはloadハンドラです。それはあなたのvar response = JSON.parse(req.responseText);行を移動する場所です。


PS。 preventDefault()はあなたの状況に完全に無関係です。「send()関数が終了するのを待つ」ために使用することはできません。イベントを処理するとき(例:<form>の場合はonsubmit)、このイベントが発生したときにブラウザがデフォルトで行う処理(フォームの送信時には<form>)を防止したい場合に使用します。

PPS。基本を見つけて、2つ以上のコールバックが連続しているコードを書き始めると、「約束」を調べます。

PPPS。 [*] このコメントを無視して、この段階であなたを混乱させるだけで正確に追加しました:"generator"を書いている場合や現在利用できない場合を除き、JavaScriptで「待機」することはできませんasync/await)。