Create a function for axios requests - javascript

I'm trying to created a global function for handle axios requests such post get delete put so I create a file called requests.js for example for post requests I created a function called post()
import axios from 'axios';
export const post = async (url, data, config) => {
axios.post(url, data, config).then((result)=>{
return result;
}).catch((error) => {
return error;
});
}
So now I want everywhere want to call a post request use this function instead of direct axios post call, so for example in data.js:
import {post} from './requests'
export const postMembersData = (url, data) => {
return post(url, data);
};
export const postCarsData = (url, data) => {
return post(url, data);
};
I call postMembersData function in index.js:
const postMembersDataApi = async() => {
await postMembersData(url, data).then((res)=>{
console.log(res); // handle data for view
}).catch((error)=>{
console.log(error); // handle errors for alert or etc
});
}
Everything looking good but there is a problem, when I get error such 500 or 400 or etc, it still return res not error in other hand it won't return error at all, Am I did something wrong?

try to run axios in return
export const post = async (url, data, config) => {
return axios.post(url, data, config).then((result)=>{
return result;
}).catch((error) => {
return error;
});
}
You return the result and the error correctly but to post function scope, and this function return undefined.
you need to return what returned from axios to be returned from post function.

Related

Sinon stub an axios post, the return value is a undefined and can't be resolved

function to be tested
export const get_drawing_data = (url, request_obj) => {
axios
.post(url, JSON.stringify(request_obj), {
headers: {
// Overwrite Axios's automatically set Content-Type
"Content-Type": "application/json",
},
})
.then((response) => {
return response;
})
.catch((error) => {
console.log(error);
});
};
Sinon stub is used to intercept the Axios post call. It simulates the axios.post return value which is a Promise. The resolve of the Promise takes the API response data as a value. So the following line use sinon.stub resolves function created a promise as axios post function return value.
describe("test axios get_drawing_data", () => {
it("test input and output", () => {
const requestData = {a: "hello world"};
const responseData = "hellow world";
sinon.stub(axios, "post").resolves(responseData);
const response = get_drawing_data("http://127.0.0.1/xxx", requestData);
expect(response).toEqual(["hello world"]);
});
});
The expectation is response.data should be equal to the constructed value in Promise. But actually it's a undefined.
expect(received).toEqual(expected) // deep equality
Expected: ["hello world"]
Received: undefined
There are a few problems here...
Your get_drawing_data function doesn't return anything
The Axios defaults are already perfect for posting JSON without custom headers or payload transformation
Don't catch promise rejections and transform the promise into a resolved one, especially by resolving with an undefined value. Your consumers will not handle that response correctly.
You'd probably be more interested in the Axios response data than the entire response
You should await the result of calling get_drawing_data()
Not sure why you'd expect an array when you've already told it what to return
With that in mind, try the following
export const get_drawing_data = async (url, request_obj) => {
try {
const { data } = await axios.post(url, request_obj);
return data;
} catch (err) {
console.error("get_drawing_data", err.toJSON());
throw err; // keep the promise chain rejected
}
};
or if you don't like async / await...
// note the arrow function has no `{...}`, ie an implicit return
export const get_drawing_data = (url, request_obj) =>
axios
.post(url, request_obj)
.then(({ data }) => data)
.catch((err) => {
console.error("get_drawing_data", err.toJSON());
return Promise.reject(err); // keep the promise chain rejected
});
and in your test
describe("test axios get_drawing_data", () => {
it("test input and output", async () => { // async function here
const url = "http://127.0.0.1/xxx";
const requestData = { a: "hello world" };
const responseData = "hellow world";
// resolve with something closer to the Axios response schema
sinon.stub(axios, "post").resolves({ data: responseData });
// await the result
const response = await get_drawing_data(url, requestData);
// verify the stub was called as expected
sinon.assert.calledWith(axios.post, url, requestData);
// compare the response with what you actually set up
expect(response).toEqual(responseData);
});
});

How can I send data on a get and receive a return?

I have to send this data in a get request but I don't know how to do it. Can you help me?
const ROUTE = "public/v1/route";
export async function showRoute(
flow: string,
token: string
): Promise<RouteParams> {
const response = await client.get(ROUTE);
return response.data;
}
You can use async/await or .then() promise chaining:
import {showRoute} from './path-to-showRoute'
showRoute(/* params */).then(data => sendGetRequest(data))
//or
async function sendRouteInfo(){
const routeData = await showRoute(/* params */)
if (routeData) sendGetRequest(routeData)
}
PS: sendGetRequest is a mock function which simply sends a get request using axios or fetch
axios.get(${URL})
.then(response => console.log(response.data)
.catch(err)=> console.log(err)
That is when you are using axios (npm i axios) then import it
I think what you're looking for is the Fetch-API. For example,
const ROUTE = resourcePath + '?' + new URLSearchParams({ ...params })
fetch(ROUTE) // sends a GET request
.then((res: Response) => res.json() as MyExpectedDataType) // parses JSON response content
.then((data: MyExpectedDataType) => {
// do something with data
})
.catch(err => {
})
// or
async function showRoute(): Promise<Something> {
try {
const res: Response = await fetch(ROUTE)
const data = await res.json() as MyExpectedDataType
// do something with data
}
catch (err) {
}
}
fetch returns a Promise type on which you can chain asynchronous callbacks using .then and handle errors with .catch and .finally. You can also pass request method, headers, body content etc. as an optional second argument to fetch, see the documentation.

Async Await of imported asynchronous function not waiting correctly

I'm flummoxed.
I have created an asynchronous utility function that I am exporting from one file and importing into a React Class Component.The function makes an API call to an authentication service which returns an object.
My goal is to be able to call that function in my component and set the returned object equal to a variable called "tokens" which I can then further manipulate.
My problem is that no matter how I seem to format this i'm unable to get the function in the component to wait for the return of the async function before moving on.
Here is a simplified version of the utility function:
// configure and send API request using Axios library
export const retrieveTokens = async () => {
// configure request
var config = {
// configs
};
// send request
axios(config)
// handle response
.then(function (response) {
let cognitoTokens = response.data;
console.log("A:")
console.log(cognitoTokens);
return cognitoTokens;
})
// handle error
.catch(function (error) {
console.log(error);
});
};
and then this utility function is being imported into the React Class Component like so:
import React, { Component } from "react";
import { retrieveTokens } from "./utils.js";
class HeaderLogic extends Component {
componentDidMount() {
async function authenticationFlow() {
let tokens = await retrieveTokens();
console.log("B:");
console.log(tokens);
}
authenticationFlow();
}
render() {
return <></>;
}
}
export default HeaderLogic;
My expected result would be:
A:
{Tokens}
B:
{Tokens}
but I am only able to get
B:
Undefined
A:
{Tokens}
I have tried various different syntax's and I simply cannot get the console logs in authenticationFlow() to await!
You forgot to return. Also, don't declare a function as async if you don't have any await inside it (not that it causes any problem but it's just useless):
// configure and send API request using Axios library
export const retrieveTokens = () => {
// configure request
var config = {
// configs
};
// send request
return axios(config)
// handle response
.then(function (response) {
let cognitoTokens = response.data;
console.log("A:")
console.log(cognitoTokens);
return cognitoTokens;
})
// handle error
.catch(function (error) {
console.log(error);
});
};

How can I write a .then function with async/await, so that I can catch the response from axios (in seperate files and methods, in vue)

My target is to catch a respone, from a axios request, which works greate with .then, but I would like use async/await, since it is a new approach with lots of benefits.
(The update method is called multiple times)
How transform my saveEdit method (which gets a response form the update method) with async/await, so that I can catch the response from axios.
Method of my .vue file:
...
saveEdit (event, targetProperty, updateValue) {
this.update(this[updateValue])
.then((result) => {
if (result.status === 200) {
this.fetchData()
this.cancelEdit()
}
})
}
...
My function of my store module:
(api is a handler for axios, basicall axios. ...)
update ({ commit, rootGetters }, details) {
...
const requestUrl = `some adress`
return api
.patch(
requestUrl,
validatedDetails
)
.then(response => {
return response
})
.catch(error => {
return Promise.reject(error)
})
}
Other stackoverflow posts related to that problem, did answer my question, since in the examples are in one file and one method.
Thanks in advance
you can try someting like:
update ({ commit, rootGetters }, details) {
...
const requestUrl = `some adress`
return api.patch(
requestUrl,
validatedDetails
)
}
and :
async saveEdit (event, targetProperty, updateValue) {
try {
const result = await this.update(this[updateValue])
if (result.status === 200) {
this.fetchData()
this.cancelEdit()
}
} catch (error) {
// handle api call error
}
}

How to mock function, that is called in "then" in axios promise?

I have a function, that is fetching data from the backend. When fetch is successful, it extracts one value from the response, and then call another function (parseAllRecordsData), that is converting the value into other value. I'm trying to test this function, but after mocking parseAllRecordsData function, it's still trying to call original function (and throws errors from that function).
In other tests jest.fn or jest.spy is working correctly, but when I'm trying to mock function that is used in "then" it's not.
export function fetchAllRecordsData(payload) {
const url = `/apis/${payload.link.split('apis/')[1]}`;
return axios.get(url)
.then(({ data }) => {
if (data && data._embedded) {
const parsedData = data._embedded['taxonomies:entry'];
const arrayData = parseAllRecordsData(parsedData, payload);
return { data: List(arrayData) };
}
return { data: List([]) };
})
.catch((error) => ({ error }));
}
And my test:
describe('fetchAllRecordsData', () => {
const mockedPayload = {
link: 'apis/ok_link',
};
beforeAll(() => {
jest.spyOn(LegalListRecordsApi,'parseAllRecordsData').mockReturnValue(['test']);
});
it('test', async () => {
const test = await LegalListRecordsApi.fetchAllRecordsData(mockedPayload);
expect(test).toEqual(1);
});
});
When it's called like this, parseAllRecordsData calls real function, and throws the error, because mocked Axios response doesn't have some values that parsing function use. I'm only interested in return value, not calling this function.
jest.spyOn(LegalListRecordsApi,'parseAllRecordsData').mockReturnValue(['test']); mocks the module export for parseAllRecordsData.
This doesn't have any effect on fetchAllRecordsData because it is in the same module as parseAllRecordsData and is calling it directly.
ES6 modules supports cyclic dependencies so you can import a module into itself.
Import the module into itself and use the module to call parseAllRecordsData:
import * as LegalListRecordsApi from './LegalListRecordsApi'; // import module into itself
export function fetchAllRecordsData(payload) {
const url = `/apis/${payload.link.split('apis/')[1]}`;
return axios.get(url)
.then(({ data }) => {
if (data && data._embedded) {
const parsedData = data._embedded['taxonomies:entry'];
const arrayData = LegalListRecordsApi.parseAllRecordsData(parsedData, payload); // use the module
return { data: List(arrayData) };
}
return { data: List([]) };
})
.catch((error) => ({ error }));
}
...and the call will be mocked when you mock the module export for parseAllRecordsData.
export function fetchAllRecordsData(payload, axiosInterface = axios) {
return return axiosInterface.get(url)
. then(({ data }) => {
// your code
})
.catch((error) => ({ error }))
}
So, you need create mock object with method get, method get should return promise.

Categories

Resources