LBA
LBA

Reputation: 4099

Chaining promises for angular-translate

As someone still new to Angular I am struggling with a special promise setup to work with angular-translate.

I have a working CustomLoader for angular-translate in place which is working fine. But I have to call the CustomLoader twice (with a $translate.refresh() ) and based on an external condition the CustomLoader should either load a fixed preset of data or the same preset but merged with the result of an external backend call.

This is what I got so far:

(function () {
  'use strict';

/**
 * TranslationCustomLoader
 */
angular
   .module('myApp')
   .factory('TranslationCustomLoader', TranslationCustomLoader);

function TranslationCustomLoader($q, ENV, $http, ExternalService) {

return function (options) {

  var translations_en = {
    MYKEY1: 'Value1',
    MYKEY2: 'Value2',
    MYKEY3: 'Value3'
  };

  var translations_de = {
    MYKEY1: 'Wert1',
    MYKEY2: 'Wert2',
    MYKEY3: 'Wert3'
  };

  var deferred = $q.defer(), translations;

// Standard Dataset for Translations based on options.key (= language key)

  if (options.key === 'en') {
    translations = translations_en;
  } else {
    translations = translations_de;
  }

 // If some condition is met call external backend and retrieve additional data

  if (ExternalService.isCondition()) {
    $http({
      method: 'GET',
      params: {
        lang: options.key
      },
      url: ENV.apiEndpoint + 'api/v1/translations'
    }).success(function (data) {

 // Now replace/add data in variable 'translations' by external result
 // External result could be: [MYKEY2: 'AnotherValue', MYKEY4: 'AdditionalValue']

      angular.forEach(data, function (value, key) {
        translations[key] = value;
      });

// Return 'merged' promise

      deferred.resolve(translations);
      return deferred.promise;
    })
  } else {

// Return 'standard' promise

    deferred.resolve(translations);
    return deferred.promise;
  }
   }}})();

The CustomLoader is called,

in case that the external condition is false the standard promise is returned and successfully resolved by $translate.

in case that external condition is true, I can see the external backend is called, I even see the results, but I got an 'cannot read .then of undefined' as it seems the promise is not correct.

Can anybody help me to fix this? I tried a lot already (including some desperate $q.all, .when etc.).

Using the partial loader (which is offered by angular-translate) isn't an alternative unfortunately.

Upvotes: 0

Views: 555

Answers (1)

JB Nizet
JB Nizet

Reputation: 692023

You're not returned anything from your function when isCondition() is true.

You're also using success(), which is deprecated, and doesn't allow chaining promises.

And if the http call fails, you never reject your promise. That, again is solved automatically by using chaining.

The code should rather look like

function (options) {

  var translations_en = {
    MYKEY1: 'Value1',
    MYKEY2: 'Value2',
    MYKEY3: 'Value3'
  };

  var translations_de = {
    MYKEY1: 'Wert1',
    MYKEY2: 'Wert2',
    MYKEY3: 'Wert3'
  };

  var translations;

  // Standard Dataset for Translations based on options.key (= language key)

  if (options.key === 'en') {
    translations = translations_en;
  } else {
    translations = translations_de;
  }

 // If some condition is met call external backend and retrieve additional data

  if (ExternalService.isCondition()) {
    return $http({
      method: 'GET',
      params: {
        lang: options.key
      },
      url: ENV.apiEndpoint + 'api/v1/translations'
    }).then(function (response) {

      // Now replace/add data in variable 'translations' by external result
      // External result could be: [MYKEY2: 'AnotherValue', MYKEY4: 'AdditionalValue']

      angular.forEach(response.data, function (value, key) {
        translations[key] = value;
      });

      // Return 'merged' promise

      return translations;
    });
  } else {
    return $q.when(translations);
  }
}

Upvotes: 2

Related Questions