Как вызвать функцию ПОСЛЕ выполнения промисов?

rocket27

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

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

У меня не получается сделать вызов этой функции ПОСЛЕ того как отработают оба http запроса и массивы заполнятся объектами из ответа, чтобы функции было с чем работать. Что бы я ни делал, вызов функции происходит раньше выполнения асинхронных запросов. Пробовал делать как здесь, использовал как Promise.all() так и ангуляровский $q, все равно вызов функции отбора результатов происходит раньше чем приходит ответ от api.

Фактори выполняющая запрос к api:

angular.module('requestToApi', [])
  .constant('clientID', 'myClientID')
  .factory('getResponseApi', function(clientID, $http) {
    return {
      request: function (tag) {
        return $http({
          method: 'GET',
          url: 'https://api.instagram.com/v1/tags/' + tag + '/media/recent',
          params: {access_token: clientID}
        })
      }
    }
  });

Контроллер:

angular.module("app").controller("appCtrl", ['$scope', 'getResponseApi', '$q', '$interval',
  function($scope, getResponseApi, $q, $interval, $stateProvider) {

    $scope.dataStorage1 = [];
    $scope.dataStorage2 = [];
    $scope.commonDataStorage = [];

    $scope.tag1 = "nature";
    $scope.tag2 = "mountains";

    $scope.getDataLeft = function() {
      getResponseApi.request($scope.tag1).then(function(response) {
        $scope.dataStorage1 = response.data.data;
      });
    };

    $scope.getDataRight = function() {
      getResponseApi.request($scope.tag2).then(function(response) {
        $scope.dataStorage2 = response.data.data;
      });
    };

    $scope.appStart = function() {
      $q.all([$scope.getDataLeft(), $scope.getDataRight()]).then(function() {
        getCommonData();
      })
    };

    $scope.appStart();

    function getCommonData() {
      let commonArray = [],
      val1, val2;

      for(val1 of $scope.dataStorage1) {
        for (val2 of $scope.dataStorage2) {
          if (val1.caption.id === val2.caption.id) {
            commonArray.unshift(val1);

            $scope.commonDataStorage = (commonArray.filter((item) => itemCheck(item)));
          }
        }
      }
    }

    function itemCheck(item) {
      let temp = [];

      if (temp.indexOf(item.caption.id) === -1) {
        temp.unshift(item.caption.id);
        return true
      }

      return false;
    }

  }]);

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

$scope.appStart = function() {
  $q.all([$scope.getDataLeft(), $scope.getDataRight()]).then(function() {
    getCommonData();
  })
};

но магия не происходит. Подскажите что делаю не так?

Так же хотелось бы вынести функцию getCommonData в отдельный factory, можно ли это сделать если она использует $scope?

1 ответ

rocket27

$http возвращает промис в angular, в getResponseApi вы используете его правильно, а getData* не возвращает ничего.

Вариант перевозврата промиса от getResponseApi

$scope.getDataLeft = function () {
    return getResponseApi.request($scope.tag1);
};

$scope.getDataRight = function () {
    return getResponseApi.request($scope.tag2);
};

$scope.appStart = function () {
    $q.all([$scope.getDataLeft(), $scope.getDataRight()]).then(function (response1, response2) {
        $scope.dataStorage1 = response1.data.data;
        $scope.dataStorage2 = response2.data.data;
        getCommonData();
    })
};

И вариант с новым промисом в getData*:

$scope.getDataLeft = function () {
    return $q(function(resolve, reject) {
        getResponseApi.request($scope.tag1).then(function (response) {
            $scope.dataStorage1 = response.data.data;
            resolve();
        });
    });
};

$scope.appStart = function () {
    $q.all([$scope.getDataLeft(), $scope.getDataRight()]).then(function () {
        getCommonData();
    })
};

licensed under cc by-sa 3.0 with attribution.