Ожидание завершения функции вызова перед итерацией вперед

0

Я здесь немного привязан к коду, который мне нужно написать. На данный момент я пытаюсь выполнить итерацию по массиву строк. После того, как найден определенный текст, если значение истинно, значение привязано к объекту timeObject.img. После этого на сервер должен быть сделан вызов для получения некоторой информации и привязки к тому же временному объекту как второму свойству (temporObject.url). К сожалению, вызов разрешен, вероятно, после завершения итерации, потому что он не добавляет этого, добавляет URL-адрес из вызова на сервер в объекте. Библиотеки, которые я использую, - angularjs и jquery.

Вот часть кода, который я написал.

$scope.Data = [];
var strArray = ["img1", "link", "img2", "link2", "img3", "link3"];
var re1 = /<img/;
for(var i = 0 ; i < strArray.length ; i++) {
    var tempObject = {};
    var test = re1.test(strArray[i]);
    if (test){
    tempObject.img = strArray[i + 1];
    myAngularService.getServerInformation().then(function(result){
        tempObject.url = result;
        $scope.Data.push(tempObject);
    }
   }

К сожалению, информация с сервера не поступает в то же время, что итерация, или что-то не так, поскольку $ scope.Data не будет содержать URL-адрес, запрашиваемый с сервера. Любые предложения о том, как использовать, возможно, обещание для такого кода, будут оценены. Я пробовал искать все возможные решения, но безрезультатно.

  • 0
    Вам нужно подождать, пока ВСЕ ваши звонки, сделанные из этого цикла, завершатся, прежде чем вы сможете использовать ваш $ scope.Data. Кроме того, поскольку время отклика может отличаться, объекты, которые вы помещаете в $ scope.Data, могут быть не в том порядке, в котором вы отправляли вызовы на сервер. Это то, что вы хотите?
  • 0
    Из-за закрытия все ваши обратные вызовы ссылаются на один и тот же tempObject .
Показать ещё 2 комментария

1 ответ

1
Лучший ответ

Javascript является функциональным. Другими словами:

if (true) {
    var testing = 5;
}
console.log(testing); // Logs 5

Применяя это к вашему примеру, tempObject в вашей функции .then callback ссылается на одну и ту же переменную!

Одним из решений является использование выражения Expression Exited Expression (IIFE) внутри оператора for для создания новой области:

for(var i = 0 ; i < strArray.length ; i++) {
    (function() {
        var tempObject = {}; // Is now declared within the new function
        /* ... code here ... */
    })();
}

Другое решение - просто использовать $.each (или angular.forEach):

$.each(strArray, function(index, value) {
    var tempObject = {}; // Is now declared within the new function
    /* ... code here ... */
}); 

Что касается ожидания завершения всех ваших вызовов, одно решение заключается в сохранении ваших обещаний в массиве с использованием угловой службы $ q:

$scope.Data = [];
var promises = [];
var strArray = ["img1", "link", "img2", "link2", "img3", "link3"];
var re1 = /img/;
$.each(strArray, function (index, value) {
    var tempObject = {};
    var test = re1.test(value);
    if (test) {
        tempObject.img = strArray[index + 1];

        var myPromise = myAngularService.getServerInformation();

        myPromise.then(function (result) {
            tempObject.url = result;
            $scope.Data.push(tempObject);
        }

        promises.push(myPromise);
    }
})

$q.all(promises).then(function() {
    // All calls will have finished
    console.log($scope.Data); 
}, function() {
    // At least 1 call failed!
    console.log("an error occurred!");
});
  • 0
    Очень хороший ответ! Другой вариант вместо $ .each или IIFE - определить вторичную функцию, в которую вы передаете tempObject, и которая выполняет вызов getServerInformation (). Тогда каждый объект tempObject также будет в правильной области видимости. Вот как я сейчас сделал что-то подобное - вы бы посчитали эту практику не такой хорошей или просто другой?
  • 0
    @ user2415266 Это решение также хорошо - и, вероятно, более читабельно в некоторых случаях.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню