0

Now I have the following information (user data) to save. I have to send it to two APIs (URL). Like this.

http://api_url/users
http://api_url/user-card

Now i need send data to several API (URL) for save user and users' card information. I have the following data:

const [data] = useState({
    last_name: "",
    first_name: "",
    middle_name: "",
    card_number: "",
    card_given_date: "",
});

And like this post request using axios.

 api.post("/users", params)
        .then(res => {
            let response = res.data;
            console.log("Saved");
            setLoadingBtn(false);
            window.location = "/user/card/" + response.id;
        })
        .catch(e => {
            console.log(e.toString());
            setLoadingBtn(false);
        })

It works correctly for one API. I need to send the First Name, Last Name and Middle name to /users and user_id, card_number and card_given_date to the second api. What variants can I use to send POST requests to several APIs at the same time? Thanks!

UPDATED! Here's another logic. axios.all() and promises.all() are good solutions to get requests. But if we use them. Suppose a field in a table is empty or an error is filled. In this case the error is only transferred to one table and the other is saved. This leads to an error of logic. Like this:

 const addUserInfo = api.postItem("users", params);
        const addCardInfo = api.postItem("user-card", params2);
        Promise.all([addUserInfo, addCardInfo])
            .then(res => {
                let response = res.data;
                console.log("Saved");
                setLoadingBtn(false);
                window.location = "/user/card/" + response.id;
            })
            .catch(e => {
                console.log(e);
                console.log(e.toString());
                setLoadingBtn(false);
            });

This way leads to confusion of logic.

Oktam Yaqubov
  • 113
  • 12
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all – Alexander Staroselsky Jan 07 '20 at 13:14
  • What's wrong with one more api.post("/user-card", params) after the first call? – Flemin Adambukulam Jan 07 '20 at 13:15
  • @FleminAdambukulam i think this is not good idea. Every data should be store in parallel. – Oktam Yaqubov Jan 07 '20 at 13:20
  • Well no matter what you use, each API will be called after another as javascript is single threaded..I don't understand what parallel storing is but assuming you have to store everything together this needs to be handled on the server side. A new API that takes all the parameters and then calls the other two apis probably – Flemin Adambukulam Jan 08 '20 at 04:09
  • @FleminAdambukulam I want to work with post requests. There is a disadvantage here. If something went wrong, it was saved to the first table but not saved to the second. The logic is broken. Looks like my edited question means. – Oktam Yaqubov Jan 08 '20 at 06:54
  • Well then it seems you need to call the second api inside .then() callback of the first api..that way second api will only be called if the first API is successful...on error you need to figure out yourself what needs to be done – Flemin Adambukulam Jan 08 '20 at 08:50
  • added an answer to explain in detail – Flemin Adambukulam Jan 08 '20 at 08:54

3 Answers3

3

Using javascript fetch API or axios.post() method will return a promise.

The Promise.all() requires an array of promises. For example:

Promise.all([promise1, promise2, promise3])

Example...

let URL1 = "http://api_url/users"
let URL2 = "http://api_url/users-card"

const promise1 = axios.post(URL1, params1);
const promise2 = axios.post(URL2, params2);

Promise.all([promise1, promise2]).then(function(values) {
  console.log(values);
});

You might wonder how the response value of Promise.all() looks like.
Have a look at this example:

var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
});
// expected output: Array [3, 42, "foo"]

Promise.all will only continue if all promises in the array are resolved.
If any promise in the array fails/reject, then the Promise.all will be rejected as well.

For more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Duplicate from : Promise All with Axios

Jozzeh
  • 841
  • 10
  • 28
  • This is a good option. But I want to work with post requests. There is a disadvantage here. If something went wrong, it was saved to the first table but not saved to the second. The logic is broken. – Oktam Yaqubov Jan 08 '20 at 06:36
2

Based on your edit and comments you need to call the second api on the success of the first api like this:

api.post("/users", params)
    .then(res => {
       let response = res.data;
       api.post("/users-card", params).then(res => {
           console.log("Saved");
           setLoadingBtn(false);
           window.location = "/user/card/" + response.id;
       });
   }).catch(e => {
        console.log(e.toString());
        setLoadingBtn(false);
    })
0

Using redux-saga or using promises or literally any other method will make more sense but this can work too:

function makeRequest(url, params, cb){
  api.post(url, params)
        .then(res => {
             //whatever you do
             cb()
        })
        .catch(e => {
            //however you behave
             cb()
        })
}

and call it like this:

makeRequest("/users", params, ()=>{
    makeRequest("/user-card",params)
})

And you can make things a bit more messy:

function call(urlArr=['/users','/user-cards'],params){
    makeRequest(urlArr[this.state.counter],params,()=>{
        this.setState((prevState)=>({
            counter : prevState.counter+1
        }),()=>{
            if(this.state.counter<urlArr.length){
                call(['/users','/user-cards'], params)
            }
        )
    })
}
E_net4
  • 27,810
  • 13
  • 101
  • 139
punjira
  • 818
  • 8
  • 21