Подтвердить что ты не робот

AngularJs: метод возвращаться синхронно, когда он называет $http или $resource внутренне

Есть ли способ подождать обещания, чтобы вы могли получить от него фактический результат и вернуть его вместо того, чтобы возвращать само обещание? Я думаю о чем-то подобном тому, как работает ключевое слово С# с задачами.

Вот пример того, почему я хотел бы иметь такой метод, как canAccess(), который возвращает true или false вместо обещания, чтобы его можно было использовать в выражении if. Метод canAccess() сделает вызов AJAX с использованием $http или $resource, а затем каким-то образом дождитесь, пока обещание будет устранено.

Будет выглядеть примерно так:

$scope.canAccess = function(page) {
    var resource = $resource('/api/access/:page');
    var result = resource.get({page: page});

    // how to await this and not return the promise but the real value
    return result.canAccess;
}

Есть ли способ сделать это?

Спасибо.

4b9b3361

Ответ 1

В общем, плохая идея. Позвольте мне рассказать вам, почему. JavaScript в браузере - это в основном однопоточный зверь. Подумайте об этом, это однопоточно в Node.js. Таким образом, все, что вы делаете, чтобы не "возвращаться" в тот момент, когда вы ожидаете, что удаленный запрос будет успешным или завершится неудачно, скорее всего, приведет к некоторому циклу для задержки выполнения кода после запроса. Что-то вроде этого:

var semaphore = false;
var superImportantInfo = null;

// Make a remote request.
$http.get('some wonderful URL for a service').then(function (results) {
  superImportantInfo = results;

  semaphore = true;
});

while (!semaphore) {
  // We're just waiting.
}

// Code we're trying to avoid running until we know the results of the URL call.
console.log('The thing I want for lunch is... " + superImportantInfo);

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

// Make a remote request.
$http.get('some wonderful URL for a service').then(function (results) {
  // Code we're trying to avoid running until we know the results of the URL call.
  console.log('The thing I want for lunch is... " + results);
});

// Continue on with other code which does not need the super important info or 
// simply end our JavaScript altogether. The code inside the callback will be 
// executed later.

Идея состоит в том, что код в обратном вызове будет инициироваться событием всякий раз, когда возвращается служебный вызов. Потому что события обусловлены тем, как нравится JavaScript. Таймеры в JavaScript - это события, действия пользователей - события, HTTP/HTTPS-вызовы для отправки и получения данных, генерирующих события. И вы должны структурировать свой код, чтобы реагировать на эти события, когда они приходят.

Можете ли вы не структурировать свой код так, чтобы он думал, что canAccess является ложным до тех пор, пока не вернется вызов удаленной службы, и, возможно, он узнает, что это действительно правда? Я делаю это все время в коде AngularJS, где я не знаю, какой конечный набор разрешений я должен показать пользователю, потому что я еще не получил их или я не получил все данные для отображения в сначала. У меня есть значения по умолчанию, которые отображаются до тех пор, пока реальные данные не вернутся, а затем страница изменится на новую форму на основе новых данных. Двусторонняя привязка AngularJS делает это очень легко.

Ответ 3

Мой подход заключался в создании функции с объектами OLD javascript следующим образом:

var globalRequestSync = function (pUrl, pVerbo, pCallBack) {

        httpRequest = new XMLHttpRequest();
        httpRequest.onreadystatechange = function () {

            if (httpRequest.readyState == 4 && httpRequest.status == 200) {
                pCallBack(httpRequest.responseText);
            }
        }
        httpRequest.open(pVerbo, pUrl, false);
        httpRequest.send(null);

    };

Ответ 4

Недавно я столкнулся с этой проблемой и сделал утилиту под названием syncPromises. Это в основном работает, отправив то, что я назвал "инструкционным списком", который будет представлять собой массив функций, которые будут вызываться по порядку. Вам нужно будет вызвать первый, затем(), чтобы начать игру, динамически присоединить новый .then(), когда ответ возвращается со следующим элементом в списке команд, поэтому вам нужно будет отслеживать индекс.

// instructionList is array.
function syncPromises (instructionList) {
  var i = 0,
    defer = $q.defer();

  function next(i) {

    // Each function in the instructionList needs to return a promise
    instructionList[i].then(function () {
      var test = instructionList[i++];
      if(test) {
        next(i);
      }
    });
  }

  next(i);

  return defer.promise;
}

Ответ 5

Вы не можете - нет никаких функций в angular, Q (promises) или javascript (на данный момент времени), которые позволяют это сделать.

Вы будете, когда ES7 произойдет.

Вы можете, если используете другую фреймворк или транспилер (как указано в статье, связанной - Transciler Transpiler или Spawn).

Вы можете, если будете выполнять свою собственную реализацию!