Перейти к содержимому

Angularjs как return string из then

  • автор:

Promise.prototype.then()

Метод then() возвращает Promise . Метод может принимать два аргумента: колбэк-функции для случаев выполнения и отклонения промиса.

Примечание: Если один или оба аргумента отсутствуют или их значения не функции, то then пропустит их и не выбросит ошибку. Если для Promise , который переходит в состояние выполнен или отклонён вызван метод then , и у данного метода нет нужного обработчика, то в таком случае then просто возвращает промис с состоянием начального Promise , для которого then был вызван.

Синтаксис

p.then(onFulfilled[, onRejected]); p.then(value => < // выполнение >, reason => < // отклонение >);

Параметры

onFulfilled Необязательный

Function вызывается, когда Promise выполнен. Эта функция принимает один аргумент, значение с которым промис был выполнен. Если значение onFulfilled не функция, то оно автоматически заменяется на «Identity» функцию (возвращает полученный аргумент)

Function вызывается, когда Promise отклонён. Эта функция принимает один аргумент, значение с которым промис был отклонён. Если значение onRejected не функция, то оно автоматически заменяется на «Thrower» функцию (выбрасывает полученный аргумент как ошибку)

Описание

Так как и метод then , и метод Promise.prototype.catch() возвращают Promise , их можно вызвать цепочкой — эта операция называется соединение.

Примеры

Использование метода then

var p1 = new Promise(function (resolve, reject)  resolve("Успех!"); // или // reject("Ошибка!"); >); p1.then( function (value)  console.log(value); // Успех! >, function (reason)  console.log(reason); // Ошибка! >, ); 

Соединение

Так как метод then возвращает промис ( Promise ), вы можете объединить несколько вызовов then в цепочку. Значения возвращаемые из колбэков onFulfilled или onRejected будут автоматически обёрнуты в промис.

var p2 = new Promise(function (resolve, reject)  resolve(1); >); p2.then(function (value)  console.log(value); // 1 return value + 1; >).then(function (value)  console.log(value); // 2 >); p2.then(function (value)  console.log(value); // 1 >); 

Вы также можете соединить одну функцию, имеющую подобный с промисами API, с другой функцией.

function fetch_current_data()  // API функции fetch() возвращает промис. Эта функция // имеет аналогичный API, за исключением значения в случае выполнения return fetch("current-data.json").then((response) =>  if (response.headers.get("content-type") != "application/json")  throw new TypeError(); > var j = response.json(); // можем что-нибудь делать с j return j; // в случае выполнения промиса, значение // передаётся в fetch_current_data().then() >); > 

Если onFulfilled возвращает промис, возвращаемое значение может быть выполнено (resolved) / отклонено (rejected) промисом.

function resolveLater(resolve, reject)  setTimeout(function ()  resolve(10); >, 1000); > function rejectLater(resolve, reject)  setTimeout(function ()  reject(20); >, 1000); > var p1 = Promise.resolve("foo"); var p2 = p1.then(function ()  // Возвращает промис, который будет разрешен значением 10 через 1 секунду return new Promise(resolveLater); >); p2.then( function (v)  console.log("resolved", v); // "resolved", 10 >, function (e)  // не вызвано console.log("rejected", e); >, ); var p3 = p1.then(function ()  // Возвращает промис, который будет отброшен значением 20 через 1 секунду return new Promise(rejectLater); >); p3.then( function (v)  // не console.log("resolved", v); >, function (e)  console.log("rejected", e); // "rejected", 20 >, ); 

Спецификация

Specification
ECMAScript Language Specification
# sec-promise.prototype.then

Совместимость с браузерами

BCD tables only load in the browser

Смотрите также

  • Promise
  • Promise.prototype.catch()

Return string from promise result

I want to have an wrapper function arround this $translate service: https://angular-translate.github.io/docs/#/guide/03_using-translate-service so we can use those function easily in our code by calling $language.translate(‘keyword’) instead of the promise. So, I create a new service in my app which should do that work. It’s a very simple function but it’s returning undefined or [Object Object] .

 angularApp.factory("$language", ['$translate', function($translate)< function trans(keyword)< console.log("translate in $language", keyword); return $translate(keyword).then(function(msg) < console.log("translation successfull", msg); return msg; >, function(translationId)< console.log("translation is not known", translationId); return translationId >) > return < translate : trans >>]); 

In both cases, when translation is known or not, the console.log() shows me the right string, but on my page it’s showing [object object] or undefined (when I remove the first return right before $translate(keyword) . When I use the filter like <<:: "KEYWORD" | translate>> it works fine. How can I let my function return the string with the translation or the translationId (which is actually the same as the keyword when there is no translation found)?

  • angularjs
  • angular-promise
  • angular-translate

Simple Angular function returning as string [closed]

Closed. This question is off-topic. It is not currently accepting answers.

Programming questions not specific to Salesforce are off-topic here, but can be asked on Stack Overflow.

Closed 8 years ago .

I am trying to create a simple Angular code base where I am trying to concatenate 2 different values in a angular controller method, but it returns the complete method as its value rather than calculating the value.. Please help.

    

Input something in the input box:

First Name -

Last Name -

Full Name - >

Console log gives me following output —

Promise-ы в AngularJS

Одной из ключевых составляющих практически любого веб-приложения является взаимодействие с сервером. В больших приложениях это далеко не один запрос. При этом запросы часто необходимо объединять для последовательного или параллельного выполнения, а часто сочетать и то и другое. Кроме того, большие приложения обычно имеют многослойную архитектуру — обертка над RESTFul API => бизнес-сущности => более комплексная бизнес-логика (разбиение условно для примера). И на каждом слое необходимо принять данные в одном формате и передать на следующий слой уже в другом.

Вот со всеми этими задачами могут помочь справиться Promise-ы.

За подробностями добро пожаловать под кат.

Promise-ы предоставляют интерфейс для взаимодействия с объектами, содержащими результат выполнения некоторой операции, время окончания которой неизвестно. Изначально любой promise не разрешен (unresolved) и будет разрешен либо с определенным значением (resolved), либо отвергнут с ошибкой (rejected). Как только promise становится разрешен или отвергнут, его состояние уже не может измениться, что обеспечивает неизменность состояния в течение какого угодно числа проверок. Что не означает, что на разных этапах проверок вы получите одно и тоже значение.

Кроме того, promise-ы можно объединять как для последовательного, так и для параллельного исполнения.

Далее все описание будет построено на базе AngularJS 1.1.5, а все примеры будут исполнены в виде тестов.

  • then(successCallback, errorCallback) ;
  • always(callback) ;
  • $http — сервис для выполнения AJAX-запросов;
  • $timeout — AngularJS-обертка над setTimeout ;
  • различные методы $q — сервиса для создания своих deferred-объектов и promise-ов.

Далее последовательно пройдемся по всем вариантам работы с promise-ами.

Простейшее использование
 var responseData; $http.get('http://api/user').then(function(response)< responseData = response.data; >); 

Ничего интересного — callback и все. Но надо же от чего-то отталкиваться в изложении. 🙂

Возврат значения из обработчиков
 var User = function(data)< return angular.extend(this, data); >; $httpBackend.expectGET('http://api/user').respond(200, < result: < data: [], page: 1, total: 10 > >); var data = <>; $http.get('http://api/user').then(function(response)< var usersInfo = <>; usersInfo.list = _.collect(response.data.result.data, function(u)< return new User(u); >); usersInfo.total = response.data.result.total; return usersInfo; >).then(function(usersInfo)< data.users = usersInfo; >); 

Благодаря такой цепочке then -ов можно строить многослойное приложение. ApiWrapper сделал запрос, выполнил общие обработчики ошибок, отдал данные из ответа без изменений на следующий слой. Там данные преобразовали нужным образом и отдали на следующий. И т.д.

Любое возвращаемое значение из then придет в success — callback следующего then . Не вернули ничего — в success-callback придет undefined (см. тесты).

Чтобы сделать reject — необходимо вернуть $q.reject(value) .

 $httpBackend.expectGET('http://api/user').respond(400, ); var error; $http.get('http://api/user').then( null, function(response)< if (response.data && response.data.error_code == 10)< return < list: [], total: 0 >; > return $q.reject(response.data ? response.data.error_code : null); > ).then( null, function(errorCode) < error = errorCode; >); 
Цепочки вызовов
 $httpBackend.expectGET('http://api/user/10').respond(200, ); $httpBackend.expectGET('http://api/group/1').respond(200, ); var user; $http.get('http://api/user/10').then(function(response)< user = response.data; return $http.get('http://api/group/' + user.group_id); >).then(function(response)< user.group = response.data; >); 

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

Параллельное выполнения запросов с ожиданием всех

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

 $httpBackend.expectGET('http://api/obj1').respond(200, ) var obj1, obj2; var request1 = $http.get('http://api/obj1'); var request2 = $timeout(function()< return ; >); $q.all([request1, request2]).then(function(values)< obj1 = values[0].data; obj2 = values[1]; >); expect(obj1).toBeUndefined(); expect(obj2).toBeUndefined(); $httpBackend.flush(); expect(obj1).toBeUndefined(); expect(obj2).toBeUndefined(); $timeout.flush(); expect(obj1).toEqual(); expect(obj2).toEqual(); 
 $q.all(< obj1: $http.get('http://api/obj1'), obj2: $timeout(function()< return ; >) >).then(function(values)< obj1 = values.obj1.data; obj2 = values.obj2; >); 
$q.when

Обернет любой объект в promise-объект. Чаще всего необходимо для моков в юнит-тестах. Или когда есть цепочка запросов, один из которых нужно выполнять не всегда, а только в некоторых случаях, а в остальных случаях есть уже готовый объект.

 spyOn(UserApi, 'get').andReturn($q.when()); var res; UserApi.get(1).then(function(user)< res = user; >); $rootScope.$digest(); expect(res).toEqual(); 

Обратите внимание, что для разрешения promise-ов должен быть выполнен хотя бы один $digest цикл.

Создание своих deferred -объектов

$q -сервис также позволяет обернуть любую асинхронную операцию в свой deferred-объект с соответствующим ему promise-объектом.

 var postFile = function(name, file) < var deferred = $q.defer(); var form = new FormData(); form.append('file', file); var xhr = new XMLHttpRequest(); xhr.open('POST', apiUrl + name, true); xhr.onload = function(e) < if (e.target.status == 200) < deferred.resolve(); >else < deferred.reject(e.target.status); >if (!$rootScope.$$phase) $rootScope.$apply(); >; xhr.send(form); return deferred.promise; >; 
  • создание своего deferred объекта: var deferred = $q.defer()
  • его разрешение в нужный момент: deferred.resolve()
  • или reject в случае ошибки: deferred.reject(e.target.status)
  • возврат связанного promise-объекта: return deferred.promise
Особенности AngularJS

Во-первых, $q-сервис реализован с учетом dirty-checking в AngularJS, что дает более быстрые resolve и reject, убирая ненужные перерисовки браузером.
Во-вторых, при интерполяции и вычислении angular-выражений promise-объекты интерпретируются как значение, полученное после resolve.

 $rootScope.resPromise = $timeout(function()< return 10; >); var res = $rootScope.$eval('resPromise + 2'); expect(res).toBe(2); $timeout.flush(); res = $rootScope.$eval('resPromise + 2'); expect(res).toBe(12); 

Это означает, что если следить за изменением переменной через строковый watch , то в качестве значения будет приходить именно resolved-значение.

 var res; $rootScope.resPromise = $timeout(function()< return 10; >); $rootScope.$watch('resPromise', function(newVal)< res = newVal; >); expect(res).toBeUndefined(); $timeout.flush(); expect(res).toBe(10); 

Исключение составляет использование функции. Возвращаемое из нее значение будет использовано как есть, т.е. это будет именно promise-объект.

 $rootScope.resPromise = function()< return $timeout(function()< return 10; >); >; var res = $rootScope.$eval('resPromise()'); expect(typeof res.then).toBe('function'); 

Понимание этого важно при написании различных loading-виджетов, loading-директив для кнопок и т.п.

AngularJS 1.2.0 — что нового в promise-ах
  • catch(errorCallback) как укороченный синоним для promise.then(null, errorCallback) ;
  • для большей схожести с Q always(callback) переименован в finally(callback) ;
  • и самое существенное — поддержка нотификации в deferred- и promise-объектах, что удобно использовать для извещения о прогрессе и т.п. Теперь полная сигнатура promise.then выглядит как then(successCallback, errorCallback, progressCallback) , а у deferred появился метод notify(progress) .

И напоследок скриншот выполненных тестов из WebStorm 7 EAP. Все же приятную добавили интеграцию с karma.

  • angularjs
  • javascript
  • web-разработка

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *