Как из JavaScript ПОСЛЕДОВАТЕЛЬНО вызвать два серверных REST - метода?

У меня возникает такая проблема.

Есть одностраничное приложение, которое работает с сервером, дёргая по REST разные серверные методы. В какой то момент мне понадобилось по событию (например, нажатию кнопки на странице) вызвать два метода, но последовательно:

данные, которые вернет первый метод, нужно передать во второй.

Вызов REST я делаю через axios, и вызов выглядит так:

    axios.post('/api/method1/', $.param(state1))
        .then((response) => {
            console.log('on /api/method1/ response:' + JSON.stringify(response));
            ... // код использующий данные method1
        })
        .catch((error) => {
            console.log(error);
            alert('Error in request: /api/method1/');
        });

Вызов другого серверного метода такой же, с точностью до названия метода.

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

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

Я не могу объединить два метода на сервере, потому что те данные, которые передаются во второй метод, могут быть изменены на клиентской стороне. Так что решение "объединить на сервере два вызова в один" не подходит.

Единственное, что приходит в голову - это "написать второй вызов внутри первого":

    axios.post('/api/method1/', $.param(state1))
        .then((response) => {
            console.log('on /api/method1/ response:' + JSON.stringify(response));
            ... // код использующий данные method1

            axios.post('/api/method2/', $.param(state2))
                .then((response) => {
                    console.log('on /api/method2/ response:' + JSON.stringify(response));
                    ... // код использующий данные method2

                })
                .catch((error) => {
                    console.log(error);
                    alert('Error in request: /api/method2/');
                });

        })
        .catch((error) => {
            console.log(error);
            alert('Error in request: /api/method1/');
        });

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

Причем, в некотрых случаях мне надо вызывать method2 после method1, а иногда - method3 после method1.

В случае же, если я начинаю в JS - коде объединять вызовы - мне придётся предусмотреть все возможные сочетания "парных" вызовов.

Ну должен же быть способ сделать из асинхронного кода обратно синхронный?

Спасибо заранее.


Ответы (2 шт):

Автор решения: Aziz Umarov

Почему вы создаете call back hell когда манипулируете Promise

axios.post('/api/method1/', $.param(state1))
        .then((response) => {
             console.log('on /api/method1/ response:' + 
             JSON.stringify(response));
             ... // код использующий данные method1   
            return axios.post('/api/method2/', $.param(state2));
        })
        .then((responce2) => {
            console.log('on /api/method2/ response:' + 
            JSON.stringify(response2));
                ... // код использующий данные method2 
        })
        .catch((error) => {
            console.log(error);            
        });

    
→ Ссылка
Автор решения: S.H.

Пожоже, ответ оказался довольно прост.

Видимо, это единственный путь, и он заключается в том, чтобы во всём коде перейти на async-await.

Для меня было неожиданностью, что при этом ВСЕ функции должны быть помечены как async, иначе это вызывает ошибку 'Uncaught SyntaxError: await is only valid in async function'

Тогда мой код для двух последовательных вызовов стал выглядеть приблизительно так:

    async function GetDataFromServer1(arg1){
        
        var tmp_json = { "arg1" : arg1 };
        var tmp = {};
        tmp.text = JSON.stringify(tmp_json);
        
        var response = await axios.post('/api/method1/', $.param(tmp));
        
        return response;
    }


    async function GetDataFromServer2(arg2){
        
        var tmp_json = { "arg2" : arg2 };
        var tmp = {};
        tmp.text = JSON.stringify(tmp_json);
        
        var response = await axios.post('/api/method2/', $.param(tmp));
        
        return response;
    }

    async function on_load {
        var response1 = await GetDataFromServer1(1);
        // ... - здесь может быть произвольный код, формирующий arg2
        var response2 = await GetDataFromServer2(arg2);
    }

(Причем, видите, значительную часть этого кода - по три строки в каждой из двух процедур - занимает подготовка данных в нужном для передачи формате. Иначе - код можно было бы сделать еще короче)

Спасибо всем, кто обратил внимание на вопрос и помог советами!

→ Ссылка