2014-10-05 5 views
-2

Моя проблема довольно проста, и я думаю, что многие программисты уже должны были столкнуться с этим. Я использую angularjs и мой Javascript выглядит следующим образом:Возможно ли, чтобы функция не возвращалась до тех пор, пока не будет выполнено условие?

controller('myController', function()) 
{ 
    if(validateForm()) 
    { 
     //do after-validation stuff 
    } 
    validateForm = function() 
    { 
     var val = undefined; 
     $http.get('api/validate/'). 
     success(function(data){ 
      val = true; 
     }). 
     error(function(data){ 
      val =false; 
     }); 
     while(!val) 
     { // loop over till val has value 
     } 
     return val; 
    } 
} 

У меня есть два вопроса:

1) когда я делаю HTTP называть это возвращает объект обещание и решает любой успех или функции ошибки. Если это так, то цикл while в этом коде не должен быть бесконечным, но это так. По отладке я обнаружил, что если я присвою значение переменной «var», тогда будет сделан только HTTP-вызов, т. Е. Когда концы завершатся. Почему http-вызов, будучи отложенным вызовом, ждет завершения цикла while?

2) Если я удаляю цикл while, независимо от значения «var», функция возвращает. Как я могу заставить его возвращаться, только если определено «var»?

+0

Может, пожалуйста, опишите первый немного? :) –

+0

Привет, Калхано Торрес Памудита, сценарий сам по себе прост, я пытаюсь достичь - это вызов B и B, возвращающий значение, основанное на том, что A что-то делает или движется дальше. – sweetcode

+0

Возможный дубликат [Как вернуть ответ от вызова Ajax?] (Http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call) –

ответ

0

Ну, как правило, такие звонки, как это, не синхронны, сказав, что, когда ваш цикл while поражен, ваша переменная val еще не установлена. Что вы должны сделать, просто вызовите функцию в случае успеха или ошибки, и эта функция должна иметь цикл while. Или попробуйте сделать асинхронный вызов async, который я не уверен, если возможно, с выбранным методом. Так что ваш новый код будет что-то вроде

function mycallback(someval){ 
    while(!someval) 
    { // loop over till val has value 
    } 
} 
controller('myController', function()) 
{ 
    if(validateForm()) 
    { 
     //do after-validation stuff 
    } 
    function() 
    { 
     var val = undefined; 
     $http.get('api/validate/'). 
     success(function(data){ 
      val = true; 
      mycallback(val); 
     }). 
     error(function(data){ 
      val =false; 
      mycallback(val); 
     }); 


    } 
} 

в зависимости от ваших потребностей вы должны изменить поток для удовлетворения этой синхронизации/асинхронный вызова. Я не рекомендую синхронизировать вызов, поскольку он замедляет выполнение за время, когда вы получаете ответ ajax. Вы должны использовать только вызов Async.

+0

Hi Sumit , в этом случае условие if() не будет всегда ложным? – sweetcode

+0

Ну, я не уверен, почему у вас это есть, и, следовательно, я его не трогал. Я предполагаю, что это нужно для проверки другого поля, за исключением проверки, необходимой вам из ajax, если нет, то поставьте ее в функцию обратного вызова. –

1

JavaScript однопоточный, поэтому успех/отказ http никогда не выполняются, потому что цикл while продолжается. Это вызывает бесконечный цикл.

Верните обещание и используйте его в вызывающей функции.

+0

Если я вернусь к функции вызова и сделаю обещание. Затем (...) там будет перемещаться элемент управления независимо от возвращаемого значения из http-вызова. Итак, что-нибудь после утверждения prmosie.then (..) будет выполнено, чего я хочу избежать. Я могу поместить всю свою логику внутри .then(), но это делает вещи очень запутанными. Выполнение if (fnCalll()) выглядит проще, чем prom.then(). – sweetcode

+0

ОК, методы успеха в сахаре и методы ошибок, добавленные к http-вызовам, не имеют значения, связанного с ними (т. Е. Нет возврата в функции обертки), поэтому значение следующего обещания будет неопределенным (я не нахожусь в компьютер, так что это может быть неверно). Либо пропустите методы сахара, то есть используйте. Then, или, в случае успеха, установите переменную в закрытии и добавьте a. Then, которая подталкивает это значение к следующему обещанию. – marneborn

0

Refactor и использовать .then

angular.module("myModule") 
.controller("myController", ["$scope", "$http", function ($scope, $http) { 

    var controller = this; 

    angular.extend(controller, { 
     // ... 
     submit : submit, 
     handleSuccess : function() { /* ... success */ }, 
     handleError : function (err) { /* error */ } 
    }); 

    function submit (form) { 
     validateForm(form) 
      .then(controller.handleSuccess, controller.handleError) 
      .then(controller.cleanUp); 
    } 

    function validateForm (form) { 
     return $http.get("...").then(function (response) { return response.data; }); 
    } 

}]); 

Это все должно быть читаемым, теперь. Кроме того, логика не входит в «успех», вместо этого она переходит внутрь последующих вызовов .then, поэтому вы можете сохранить свой submit чистым и читаемым.

Но вы можете не когда-либо сделать что-то вроде

while (true) { 
} 

или

for (var i = 0; i < 10000000; i += 1) { } 

Все, что вы делаете блокировки вашего браузера, предотвращая людей с помощью страницы.
Вы не можете анимировать CSS, вы не можете читать значения AJAX, возможно, вы даже не можете закрыть вкладку (в зависимости от браузера).

Все должно быть либо реактивным (основанным на событиях), либо асинхронным, с использованием обратных вызовов или обещаний.

Смежные вопросы