2

我是 JavaScript 新手,我四处寻找解决问题的方法。我真的很难找到正确的答案。我想我可能不得不对回调做一些事情,但我不确定。

基本上,我在我的网站上实现了一个“喜欢”按钮。单击“赞”按钮后,我需要完成两个主要的后端操作:更新“赞”的数据库,并向获得“赞”的人发送电子邮件通知。单击“喜欢”按钮后,我呈现一个“喜欢”按钮以向用户显示它通过了。

问题是,拍摄电子邮件需要很长时间。因此,如果我更新数据库,然后发送电子邮件,然后呈现按钮,用户将在他/她看到按钮更改为“喜欢”按钮之前等待一段时间。因此,我想更新数据库,渲染点赞按钮,然后发送电子邮件。

在我的 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 处理程序,而不是将实际函数对象分配给 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 回答