2012-06-12 3 views
6

То, с чем я боролся в прошлом, и сегодня борюсь с этим, предотвращает продолжение API/AJAX до тех пор, пока вы не получите ответ. в настоящее время я работаю с API Facebook. Мне нужно получить ответ от вызова, а затем вернуть его, но то, что происходит, это то, что моя функция возвращается, прежде чем я получаю ответ от вызова API. Я знаю, почему это происходит, я просто не могу понять, как это предотвратить! Вот мой код ...Ожидание вызова API для завершения в Javascript перед продолжением

function makeCall(){ 

var finalresponse = ""; 
    var body = 'Test post'; 

     FB.api('/me/feed', 'post', { message: body }, function(response) { 
     if (!response || response.error) { 
     finalresponse = response.error; 
     } else { 
      finalresponse = 'Post ID: ' + response.id; 
     } 
     }); 
     return finalresponse; 

} 

// ----- EDIT

Я заметил, некоторые люди предложили что-то вроде этого ...

function makeCall(){ 
var finalresponse = ""; 
FB.api('/me/feed', 'post', { message: body }, function(response) { 
     if (!response || response.error) { 
     finalresponse = response.error; 
     return finalresponse; 
     } else { 
      finalresponse = 'Post ID: ' + response.id; 
      return finalresponse; 
     } 
     }); 
} 

Но это возвращает неопределенное

// РЕДАКТИРОВАНИЕ НА ОСНОВЕ ОБНОВЛЕНИЯ

function share_share(action_id){ 

    var finalresponse = makeCall(action_id, process); 
    return finalresponse; 

} 

function makeCall(action_id, callback){ 

var body = 'Test post'; 
     FB.api('/me/feed', 'post', { message: body }, function (response) { 
     if (!response || response.error) { 
     var finalresponse = response.error; 
     } else { 
      finalresponse = 'Post ID: ' + response.id; 
     } 
     callback(action_id, finalresponse); 
     }); 

} 
function process(action_id, finalresponse){ 
    console.log(finalresponse); 
} 
+0

Я верю, потому что ваш ответ return finalresponse; 'находится за пределами вызова API. –

+0

Ваше возвращение будет выполнено до того, как FB.api завершит – Dhiraj

+0

, код, который вы указали при редактировании, неверен. Возврат finalResponse в вашем обратном вызове будет возвращен вызывающей стороне вашего обратного вызова ответа. Причина undefined возвращается вызывающему для makeCall(), потому что make-вызов ничего не возвращает. –

ответ

13

вопрос, который задают в 100 раз в день, и кажется невозможным, чтобы иметь один ответ.

Звонок асинхронный, поэтому его невозможно сделать за один шаг. Основной пример того, что вы ожидаете.

function one() { 
    var a = 1; 
    return a; 
} 
alert(one()); 

Что на самом деле происходит:

function one() { 
    var a; 
    window.setTimeout( 
    function() { 
     a = 1; 
    }, 2000); 
    return a; //This line does not wait for the asynchronous call [setTimeout/ajax call] to run. It just goes! 
} 
alert(one()); 

Что вам нужно сделать, это разбить его на две части.

function one(callback) { 
    window.setTimeout(function(){ //acting like this is an Ajax call 
     var a = 1; 
     callback(a); 
    },2000); 
} 
function two(response) { 
    alert(response); 
} 
one(two); 

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

function makeCall(callback) { 
    var body = 'Test post'; 
     FB.api('/me/feed', 'post', { message: body }, function (response) { 
     if (!response || response.error) { 
     var finalresponse = response.error; 
     } else { 
      finalresponse = 'Post ID: ' + response.id; 
     } 
     callback(finalresponse); 
     }); 
} 


function processResponse(response) { 
    console.log(response); 
} 
makeCall(processResponse); 
+1

И @Pointy просто убил мое редактирование, время повторить его еще раз. – epascarello

+0

Спасибо, это действительно помогло мне понять, но что, если я хочу вернуть ответ на исходный звонок? См. Мое последнее изменение выше. Я хотел бы получить значение и вернуть его. Таким образом, в основном у меня есть функция, которая вызывает share_share, и она должна быть возвращена с ответом. –

+0

Он не может быть просто возвращен, он должен быть обратным вызовом. «Return finalresponse» - это то же самое, что и раньше, просто по-другому! – epascarello

6

В JavaScript нет концепции ожидания или уступки. JavaScript продолжает выполнение, без прерывания, вашего кода до конца. Сначала это кажется странным и неприятным, но оно имеет свои преимущества.

Таким образом, идея в таких сценариях, что код, который вы хотите выполнить после получения ответа, должен быть помещен в обратный вызов, который вы передаете FB.api(). Вам придется вырвать код после инструкции return в ответный ответ, чтобы он мог быть выполнен, когда получен ответ.

Это то, что вы могли бы ожидать от JavaScript, если бы это было, как и большинство языков (таких как C++/Java):

var futureResult = SomeAsyncCall(); 
futureResult.Wait(); //wait untill SomeAsyncCall has returned 
var data = futureResult.GetData(); 
//now do stuff with data 

Идея в JavaScript, однако, базируется на обратных вызовов при работе с асинхронной :

SomeAsyncCall(function(result) { 
    var data = result.GetData(); 
    //now do stuff with data 
}); 
+0

спасибо за ваше время, есть ли у вас какие-либо предложения для этого? –

+0

Я добавил пример, чтобы прояснить идею. –

0

Вы не хотите препятствовать его возврату, так как такое действие блокирует браузер пользователя в течение всего срока действия запроса. Если запрос зависает по какой-либо причине (перегрузка, обслуживание сайта и т. Д.), Браузер перестает отвечать на любые запросы пользователей, что приводит к нарушению пользователей.

Вместо того чтобы делать следующее:

var res = makeCall(); 
if(res) 
{ 
    // do stuff 
} 

ли это:

function makeCall(){ 
    FB.api('/me/feed', 'post', { message: body }, function(response) { 
     if (response && !response.error) { 
      // do stuff 
     } 
    }); 
} 

makeCall(); 
Смежные вопросы