Промисы, как работает $q в Angular

Пример работы с $q
app.controller(‘promiseController’, promiseController);

function promiseController($scope, $q, $timeout){
         $scope.myData = 'Old data'; 

    	var defer = $q.defer(); // (1)

    	defer.promise
    		.then(function(val){
    			$scope.myData = val;
    		}); // (2)

    	$timeout(function(){
    		defer.resolve('New data, baby!');
    	}, 5000)  // (3)
  }

Кто понимает объясните как работает данный код, как я понимаю
(1) - создает какую-то сущность из которой создается промис, не совсем понятно что-такое $q.defer() и зачем его использовать ведь нам нужен промис
(2) - создается промис и в нем устанавливает функцию, что выполняется после выполнения промиса
(3) - defer.resolve('New data, baby!'); - устанавливается новое значение для переменой, как понимаю resolve это метод который выполняется при успешном выполнении промиса.
Поправьте в чем не прав, спасибо

q - это библиотека для манипулирования асинхронными данными которая была инкорпорирована в ангуляр (и стала доступка как $q)
defered - это обьект с которого консструируется промис. Последний получается из первого путём вызова метода promise. $q.defer() - это приватный обьект, является , promise - публичный.

A promise is a placeholder for a result which is initially unknown while a deferred represents the computation that results in the value. Every deferred has a promise which functions as a proxy for the future result. While a promise is a value returned by an asynchronous function, a deferred can be resolved or rejected by it’s caller which separates the promise from the resolver.
взято отсюда

Более понятно будете если переделать ваш пример таким образом:

function getData (newData) {
        var myData = 'Old data'; 
    	var deferred = $q.defer();  // создаем обьект deferred

    	$timeout(function(){
    		deferred.resolve(myData + newData); // через какое-то время (асинхронно) - исполняем промис
    	}, 5000) 

       return defer.promise; //  тут же возвращяем промис
  }
getData('new data')
    .then(function(val){
    	console.log(val); // 'Old data new data' - получаем асинхронно результат
    }); 

это будет более частый и понятный вариант использования deffered;
Все что вы написали в описании (1,2,3) - верно.

1 лайк

deferred - это объект, который может не содержать в себе сейчас значения, но может зарезолвиться значением в будущем. deferred объект управляет состоянием и может в итоге вызвать метод .resolve, который установит значение deferred-а.

deferred управляет состоянием значения, а promise позволяет использовать коллбеки когда состояние значения меняется.

На самом деле промис уже создан. Он создался одновременно с созданием deferred объекта. Promise - это часть deferred объекта, которую обычно отдают потребителям значений.

Корректнее было бы сказать, что мы навесили обработчик события resolv-а значения.

Если быть более корректным, то “resolve - это метод, который нужно вызвать чтобы установить значение promis-а”.

1 лайк

Действительно, ведь promise это метод deferred

Спасибо за объяснение, возник еще вопрос

Не совсем понятно, разве resolve устанавливает значение promis'а, я вижу resolve как функцию выполняющуюся при успешном изменении состояния промиса (fulfiled), но по твоему объяснению resolve устанавливает значение promis-а

resolve - это причина fulfiled-а промиса. Вот пример на псевдокоде:

function returnsPromise() {
	var def = new Deferred()
	setTimeout(function fulfilPromiseLater() {
		def.resolve('promiseValue')
	}, 999)
	return def
}


returnsPromise().then(function (promiseValue) {
	console.log(promiseValue) // "promiseValue"
})

Функция returnsPromise вернет промис. Внутри себя она создает deferred объект. Функция не возвращает deferred объект потому что хочет удерживать контроль над тем когда установится значение promise-а. Через некоторое время функция returnsPromise резолвит промис значением 'promiseValue'. С точки зрения потребителя в этот момент выполнится коллбек, переданный в метод then промиса. Получается что причина того, что потребитель получил значением промиса именно в том, что поставщик промиса вызвал .resolve на deferred объекте.