2

私は JavaScript が初めてで、問題の解決策を探し回っています。私は正しい答えを見つけるのに本当に苦労しています。コールバックで何かをしなければならないかもしれないと思いますが、よくわかりません。

基本的に、私は自分のウェブサイトに「いいね」ボタンを実装しています。「いいね」ボタンをクリックすると、2 つの主なバックエンド処理が必要になります。「いいね」のデータベースを更新し、「いいね」を付けた人にメール通知を送信する必要があります。「いいね」ボタンをクリックした後、「いいね」ボタンをレンダリングして、それが通過したことをユーザーに示します。

問題は、メールの撮影に時間がかかることです。したがって、データベースを更新してからメールを送信してからボタンレンダリングすると、ユーザーはボタンが「いいね」ボタンに変わったことを確認するまで少し待つことになります。代わりに、データベースを更新し、いいねボタンをレンダリングしてからメールを送信したいと思います。

私のJavaScriptでは、次のことを試しました:

function foo()
{
  xmlhttp1.onreadystatechange = liked( function() {
    xmlhttp2.open("POST", "async/async_likeEmail.php",true)
    xmlhttp2.setRequestHeader(...
    ...
    xmlhttp2.send(parameters);
  }

  xmlhttp1.open("POST", "async/async_likeUpdateDB.php", true)
  xmlhttp1.setRequestHeader(...
  ...
  xmlhttp1.send(parameters);
}

function liked(callback) {
  if (xmlhttp1.readyState == 4)
  {
    xmlhttp1.responseText;
    someElement.innerHTML = xmlhttp1.responseText; // render the "liked" button
    callback();
  }
}

このようにすると、非同期の「いいね」関数の呼び出しに失敗します。何らかの理由で、コールバックを渡すと壊れます。また、コールバックを渡さずに別の「like_notify」関数を定義し、非同期の「liked」関数内で like_notify() を呼び出すことも失敗しました。

誰かが私が間違っていることと、これらの試みが失敗した理由を教えてもらえますか? コールバックはこの問題の解決策ではありませんか?

4

2 に答える 2

2

ユーザー インターフェイスを更新する許可を得るためにサーバーからの応答を待つ代わりに、UI を更新するだけで問題ないと単純に想定するのが一般的な手法です。ほとんどの場合、リクエストは通常​​成功するため、その仮定を行ってからサーバーにリクエストを送信します。

その後、応答が戻ってきたら、UI を更新する代わりに、要求が本当に成功したかどうかを確認します。もしそうなら、素晴らしい!既に UI を更新しているので、何もしないか、高速更新がサーバーから送信されたものと一致することを確認することができます。あるべきですが、そうでない場合は修正できます。

さらに、応答でステータス コードを確認することもできます。例外的なケースがあることを示す 500、404、または 200 以外のステータス コードである場合は、いいね ボタンを以前の状態に戻し、ユーザーに適切なエラー メッセージを表示することで対応できます。

これにより、UI が非常に機敏になるだけでなく、エラーが発生した場合でも対処できます。

これは、この手法を容易にするためにわずかに変更されたコードです。私はすべてのコードを持っているわけではないので、これは実用的な例として解釈されるべきではなく、単にあなたが始めることを意図しています:

function foo()
{ 
   // call liked immediately. Don't wait for the server to respond
      // think "update the UI immediately"
   liked( function() {
       xmlhttp2.open("POST", "async/async_likeEmail.php",true)
       xmlhttp2.setRequestHeader(...
       ...
       xmlhttp2.send(parameters);
   });

  // this is a handler where you just check to make sure the request succeeded
    // if it does, great, do nothing. If it fails, change the like button back!
  xmlhttp1.onreadystatechange = function() {
      if(xmlhttp1.status == 404 || xmlhttp1.status == 503) {
          alert("problem!");
          // put the like button back to the previous state
      }
  };

  xmlhttp1.open("POST", "async/async_likeUpdateDB.php", true)
  xmlhttp1.setRequestHeader(...
  ...
  xmlhttp1.send(parameters);
}

function liked(callback) {

  /* insert code to render the liked result
   *  show what the button would look like if successful.
   */

  // you don't really need to do this part. You know what a liked button looks like
   // so just render it without waiting for the response.
    // however, leaving this here acts as a failsafe in case your  
     // code that updates it immediately does something wrong
  if (xmlhttp1.readyState == 4)
  {
    xmlhttp1.responseText;
    someElement.innerHTML = xmlhttp1.responseText; // render the "liked" button

    // call the callback to make the 2nd Ajax request
    callback();
  }
}

アップデート:

最初の AJAX 呼び出しが適切に実行されなかった理由は、実際の関数オブジェクトを onreadystatechange ハンドラーに割り当てるのではなく、"liked" 関数の結果を onreadystatechange ハンドラーに割り当てていたためです。

xmlhttp1.onreadystatechange = liked( function() {
    xmlhttp2.open("POST", "async/async_likeEmail.php",true)
    xmlhttp2.setRequestHeader(...
    ...
    xmlhttp2.send(parameters);
}

代わりに、これはうまくいきました:

xmlhttp1.onreadystatechange = function() { 
    liked( function() {
        xmlhttp2.open("POST", "async/async_likeEmail.php",true)
        xmlhttp2.setRequestHeader(...
        ...
        xmlhttp2.send(parameters);
    }
}

より明確にするために、次のことを考慮してください。

xmlhttp1.onreadystatechange = someFunct();   // assign the result to the handler

xmlhttp1.onreadystatechange = someFunct;    // assign the function to the handler

// also assigns function to handler, but wrapped in anonymous function
xmlhttp1.onreadystatechange = function() {   
    someFunct();
}
于 2012-05-19T01:56:55.063 に答える
2
//abstract the ajax 
function ajaxpost(url,callback){

    //all the xhr setup stuff

    xmlhttp.open("POST", url, true)
    xmlhttp.onreadystatechange = function(){
        if (xmlhttp1.readyState == 4){

            //execute callback when done
            callback(xmlhttp.responseText);
        }
    }
    xmlhttp.send();
}

function like(){
    //update db
    ajaxpost("async/async_likeUpdateDB.php",function(data){
        //render like button
        someElement.innerHTML = xmlhttp1.responseText
        //email
        email();
    }
}

function email(){
    //hit email
    ajaxpost("async/async_likeEmail.php",function(data){
        //everything done
    }
}
于 2012-05-19T01:59:51.547 に答える