2012-05-19 8 views
2

Я новичок в JavaScript, и я искал решение проблемы. Я действительно пытаюсь найти правильный ответ. Я думаю, мне, возможно, придется что-то сделать с обратными вызовами, но я не уверен.Вызов функции после завершения асинхронной функции JavaScript?

В принципе, я реализую кнопку «как» на своем веб-сайте. При нажатии кнопки «как» мне нужны два основных элемента: «База данных« нравится »должна быть обновлена, а уведомление по электронной почте должно быть отправлено человеку, который получил« как ». После нажатия кнопки «like», я показываю кнопку «понравилось», чтобы показать пользователю, с которым она прошла.

Проблема в том, что съемка электронной почты занимает много времени. Поэтому, если я обновляю базу данных, а затем отправлю электронное письмо и , то визуализируйте кнопку, пользователь будет ждать немного, прежде чем он/она увидит, что кнопка изменена на кнопку «понравилась». Поэтому вместо этого я хотел бы обновить базу данных, отобразить понравившуюся кнопку и , затем снимать письмо.

В моей 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», а вызов as_notify() внутри асинхронной «любимой» функции также терпит неудачу.

Может ли кто-нибудь сообщить мне, что я делаю неправильно, и почему эти попытки потерпели неудачу? Являются ли обратные вызовы не решением этой проблемы?

ответ

2

Вместо того, чтобы ждать ответа от сервера, чтобы получить разрешение на обновление пользовательского интерфейса, популярным методом является просто предположить, что все в порядке, просто обновите интерфейс. В большинстве случаев запрос обычно успешный, поэтому просто сделайте это предположение, а затем сделайте запросы на сервер.

Впоследствии, когда ответ возвращается, вместо обновления пользовательского интерфейса проверьте, действительно ли запрос действительно успешный. Если бы это было здорово! Вы ничего не можете сделать, так как вы уже обновили свой пользовательский интерфейс или можете проверить, чтобы ваше быстрое обновление соответствовало тому, что отправил сервер. Он должен, но если это не так, вы можете это исправить.

Кроме того, вы также можете проверить код состояния в ответе. Если это 500, 404 или любой код состояния, отличного от 200, который указывает, что есть исключительный случай, вы можете действовать на него, вернув свою кнопку в прежнее состояние и затем отображая приятное сообщение об ошибке своему пользователю.

Это не только делает ваш пользовательский интерфейс чрезвычайно быстрым, но вы все еще можете обрабатывать условия ошибки, когда они происходят.

Вот ваш код, слегка измененный для облегчения этой техники.Так как я не весь код, это не должно быть истолковано в качестве рабочего примера и предназначено просто, чтобы вы начали:

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(); 
    } 
} 

UPDATE:

Причина ваш первый вызов AJAX не стрелял должным образом потому, что вы были назначая результат функции THH «понравилось» в обработчик 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(); 
} 
+0

Интересно. Я застрял, думая, что я должен только обновить кнопку «как», если я сделал обновление базы данных. Спасибо за это! Я все еще не понимаю, что случилось с тем, что я делал, хотя ... – bhh1988

+1

@ bhh1988 - Я обновил ответ, чтобы показать, почему ваш обработчик AJAX вообще не работает. Вы назначали результат функции toreadystatechange вместо назначения объекта функции. Удачи! – jmort253

+0

OH! Я совершенно не знал о различной семантике именных анонимных функций. Вот где я был введен в заблуждение. Благодаря! В качестве продолжения я только что закончил реализовывать вещи так, как вы предлагали, и это прекрасно работает! Спасибо! – bhh1988

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 
    } 
} 
Смежные вопросы