Есть ли какой-либо порядок методов, когда $q.all имеет несколько функций HTTP-вызова в Angularjs?

Во-первых, я плохо разбираюсь в angularjs.

Пока я изучал $q, я столкнулся со странной проблемой.

Когда я использую $q.all, я помещаю $http в обычную последовательность, ожидая получить результаты в том же порядке,

но то, что я получаю, было случайным результатом.

Посмотри на это и исправь мою глупость.

    $q.all([
        HttpService.editItem(
            $scope.$parent.category_id,           //  category id
            Define.CAR_CAT,                         //  category url to request
            $scope.car_id,                           //  car_id wanna edit
            {car_name: inputValue.toUpperCase()}    //  data
        ),
        HttpService.getCarList(
            $scope.$parent.category_id,     //  category id
            Define.CAR_CAT                    //  category url to request
        )
    ]).then(function (results) {
        if (results[0].statusText === 'OK' && results[1].statusText === 'OK') {
            .....
    });

«HttpService» — это служба моего приложения. Он возвращает обещание.

Я ожидал, что

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

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

И я использую

вернуть $ q (функция (разрешить, отклонить) {});

вместо использования

$q.defer();

.

.

.

.

и это моя часть HttpService

function editItem(cat_id, cat_url, content_id, item_data) {
    return $q(function (resolve, reject) {
        $http({
            method: 'PUT',
            url: Define.TEST_URL + cat_id + cat_url + content_id,
            data: item_data
        }).then(function (response) {
            resolve(response);
        }, function (error) {
            reject(error);
        });
    });
}



function getCarList(cat_id, cat_url) {
    return $q(function (resolve, reject) {
        $http({
            method: 'GET',
            url: Define.TEST_URL + cat_id + cat_url
        }).then(function (response) {
            resolve(response);
        }, function (error) {
            reject(error);
        });
    });
}

и вот ответ getCarList

{
    "error_msg": "",
    "error_num": 0,
    "statusText": "OK"
    "results": [
            {
            "car_id": "CAR0121",
                "car_name": "AUDI R8"
            },
            {
                "car_id": "CAR0122",
                "car_name": "AUDI A6"
            },
            {
                "car_id": "CAR0128",
                "car_name": "BENZ"
            },
            {
                "car_id": "CAR0130",
                "car_name": "PORCHE"
            },
    ]
}

person Canet Robern    schedule 11.09.2017    source источник
comment
нет, порядок абсолютно соблюден.   -  person Hitmands    schedule 11.09.2017
comment
@Hitmands Я думал, что это абсолютный порядок, но возникла проблема ..   -  person Canet Robern    schedule 11.09.2017


Ответы (3)


Если вы хотите, чтобы вызовы были последовательными, вам нужно будет вызывать их, используя цепочку промисов вместо $q.all

HttpService.editItem(
        $scope.$parent.category_id,             //  category id
        Define.CAR_CAT,                         //  category url to request
        $scope.car_id,                          //  car_id wanna edit
        {car_name: inputValue.toUpperCase()}    //  data
    )
    .then(function(result) {
        if (result.statusText === 'OK') {
            return HttpService.getCarList(
                $scope.$parent.category_id,     //  category id
                Define.CAR_CAT                  //  category url to request
            )
        }
        else {
            return $q.reject();
        }
    })
    .then(function (result) {
        if (result.statusText === 'OK') {
        .....
    });
person Icycool    schedule 11.09.2017
comment
ммм.. Я думаю, что это лучший способ для всех моих кодов. Спасибо. Это может помочь решить мою проблему :) - person Canet Robern; 12.09.2017

Есть ли порядок методов в $q.all в Angularjs?

Да, Приказ относится к приказу Обещаний, который вы отдали $q.all()

Из ссылки: $q.all()

Возвращает один промис, который будет разрешен с помощью массива/хэша значений, каждое значение соответствует промису с тем же индексом/ключом в массиве/хэше промисов. Если какое-либо из обещаний разрешается с отклонением, это полученное обещание будет отклонено с тем же значением отклонения.

Пример 1 (список)

var  promises = [promise1(), promise2(), promise3()];

$q.all(promises).then((values) => {
    console.log(values[0]); // value promise1
    console.log(values[1]); // value promise2
    console.log(values[2]); // value promise3
});

Пример 2 (карта)

var  promises = {one: promise1(), two: promise2(), three: promise3()};

$q.all(promises).then((values) => {
    console.log(values.one); // value promise1
    console.log(values.two); // value promise2
    console.log(values.three); // value promise3
});

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

Я предлагаю вам создать подход map и протестировать то, что вы получите:

$q.all({edit:
    HttpService.editItem(
        $scope.$parent.category_id,           //  category id
        Define.CAR_CAT,                         //  category url to request
        $scope.car_id,                           //  car_id wanna edit
        {car_name: inputValue.toUpperCase()}    //  data
    ),
    getCar: HttpService.getCarList(
        $scope.$parent.category_id,     //  category id
        Define.CAR_CAT                    //  category url to request
    )
}).then(function (results) {
   // results.edit
   // results.getCar 
});

ИЗМЕНИТЬ

демонстрационный планкер с использованием Map

демонстрационный планкер с использованием списка

person Maxim Shoustin    schedule 11.09.2017
comment
Ну, в моем коде http-вызов уже находится в массиве $q.all. Если я последую вашему предложению, вызывающая функция должна быть в функции «тогда» $q.all, верно? - person Canet Robern; 12.09.2017
comment
обновлен ответ, изменен на встроенный, см. $q.all({edit: .... getCar: }) - person Maxim Shoustin; 12.09.2017
comment
Результат этого был таким же, как оригинал. Я думаю, что $q.all не гарантирует порядок массива, когда http-вызов находится внутри функции, которая находится в массиве $q.all. - person Canet Robern; 12.09.2017
comment
@CanetRobern да, это гарантирует. Вы использовали карту вместо списка? Можете ли вы опубликовать демонстрацию в plunker, которая показывает вашу проблему? - person Maxim Shoustin; 12.09.2017
comment
@CanetRobern взгляните на эту демонстрационную КАРТУ: plnkr.co/edit/t9MHfCyDCBvQ0P7Cyq2d?p=preview и эта демонстрация в виде СПИСКА: plnkr.co/edit/d8mXEAfVnonqh7xBO4Xa?p=preview - person Maxim Shoustin; 12.09.2017
comment
Теперь я использовал хостинг на локальном сервере, поэтому не могу показать вам последовательности ответов http с помощью plunker. Я скопировал ваш код и вставил его, но использование карты не меняет мой результат. Возможно, $q.all может обрабатывать только результаты своих собственных массивов, а не заказы HTTP-вызовов. - person Canet Robern; 12.09.2017
comment
Функция $timeout, да, она показывает результаты такие же, как последовательности массива $q.all(). Но http-вызов, я думаю, это может произойти из-за того, что время каждого запроса или время ответа делают очень маленький разрыв. - person Canet Robern; 12.09.2017
comment
@CanetRobern совсем нет. $timeout и $http возвращают Promise. Я думаю, что что-то не так с логикой вашего сервиса. - person Maxim Shoustin; 12.09.2017
comment
Я добавил свои коды HttpService и ответ getCarList. Пожалуйста, смотрите это больше. - person Canet Robern; 12.09.2017
comment
@CanetRobern, вопрос: хотите ли вы сначала позвонить editItem, а после обновиться getCarList? - person Maxim Shoustin; 12.09.2017
comment
Да! Конечно! Мое плохое знание английского смутило тебя? Т.Т. - person Canet Robern; 12.09.2017
comment
@CanetRobern OMG, конечно, вы не можете использовать q.all, потому что в этом случае angular отправляет оба запроса одновременно. Вам поможет только цепочка обещаний - person Maxim Shoustin; 12.09.2017
comment
Что ж, тогда $q.all не может обрабатывать множественные HTTP-вызовы, как ожидалось. Спасибо за проявленный интерес! Это было очень полезно для моего углового навыка :) - person Canet Robern; 13.09.2017

но то, что я получаю, было случайным результатом.

$q.all будет ожидать одновременного выполнения промисов. Таким образом, нет никакой гарантии, какой запрос попадет на сервер первым. Но порядок ответов будет сохранен.

Если вы хотите убедиться, что вы читаете после записи, вам нужно дождаться ответа на запись, чтобы ответить, что все в порядке.

var editing = HttpService.editItem(
        $scope.$parent.category_id,           //  category id
        Define.CAR_CAT,                         //  category url to request
        $scope.car_id,                           //  car_id wanna edit
        {car_name: inputValue.toUpperCase()}    //  data
    )
 var reading = editing.then(function() {
    return HttpService.getCarList(
        $scope.$parent.category_id,     //  category id
        Define.CAR_CAT                    //  category url to request
    )
   })

//if you need both results
$q.all([editing, reading]).then(function(results) {

})
person Yury Tarabanko    schedule 11.09.2017
comment
Я думаю, что ваше предложение - хороший способ, но я не хочу разделять эти коды.. Т. Т. Но, спасибо вашему руководству - person Canet Robern; 11.09.2017
comment
@CanetRobern Тогда вы не можете быть уверены, какой запрос первым достигнет вашего сервера. Таким образом, когда-нибудь вы столкнетесь с грязными чтениями - person Yury Tarabanko; 11.09.2017
comment
Я выполнил свое приложение, следуя вашему коду, но все равно получил тот же результат. Сначала getCar, отредактируйте позже. Я думаю, что если функция в массиве $q.all имеет HTTP-вызов, это не гарантирует, что порядок ответов на HTTP-вызов такой же, как порядок массива $q.all. - person Canet Robern; 12.09.2017
comment
@CanetRobern То, что вы говорите, просто невозможно с кодом, который я опубликовал. Во-первых, $q.all ничего не знает о характере обещаний, которые он использует (поэтому он не может повлиять на порядок запросов даже в принципе). Второй getCarList вызывается после редактирования промиса (т.е. сервер ответил клиенту). - person Yury Tarabanko; 12.09.2017
comment
Ах... моя ошибка... Ваш код работает хорошо. Возможно, нет другого способа решить эту проблему, кроме как с помощью цепочки или вашего способа. Большое спасибо! - person Canet Robern; 12.09.2017