Pace-js not working with Axios inside Vue - javascript

I have the following axios call:
//Pace.restart();
Pace.start();
axios.post(`${this.url_base}/${this.system}`, consulta)
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error.response.data);
})
.then(() => {
Pace.stop();
});
However Pace.start() simply won't fire and Pace.restart() will flash briefly instead of waiting for the stop signal from axios. What am I doing wrong?

Related

Does .then wait for setState to finish before calling the next method?

I have this method in my React app:
My issue is that the createQuestions() runs before the findEmployeeId() method is done. Shouldn't the .then make it wait?
Inside the findEmployeeId() it is doing a setState operation. Does it not wait for that to finish? I need that data update before the createQuestions() runs.
createInterview() {
fetch(API_URL + `/interview/create`, {
method: "PUT",
body: JSON.stringify({
employee: this.state.employee,
employment_level: this.state.employment_level,
audit_id: this.props.auditId,
}),
headers: { "Content-Type": "application/json" },
})
.then((res) => {
if (!res.ok) {
throw new Error();
}
return res.json();
})
.catch((err) => console.log(err))
.then(() => this.findEmployeeId())
.then(() => this.createQuestions());
this.setState({ showHide: false });
}
This is the findEmployeeId method. How can I make it wait until completion before the next one runs?
findEmployeeId() {
fetch(API_URL + `/employee/${this.state.employee}/${this.props.auditId}`)
.then((res) => {
if (!res.ok) {
throw new Error();
}
return res.json();
})
.then((result) => {
this.setState({ lastEmployeeId: result[0].employee_id });
console.log(result);
})
.catch((error) => {
console.log(error);
});
}
#raina77ow wrote it in his comment already, but to state it a little more clearly, I think you need to return the promise from findEmployeeId():
findEmployeeId() {
/* Note the return here */
return fetch(API_URL + `/employee/${this.state.employee}/${this.props.auditId}`)
.then((res) => {
if (!res.ok) {
throw new Error();
}
return res.json();
})
.then((result) => {
this.setState({ lastEmployeeId: result[0].employee_id });
console.log(result);
})
.catch((error) => {
console.log(error);
});
}
The question is basically finding a way to guarantee to have createQuestions() executed after findEmployeeId(). This is the heart of the question. The use of the setState Callback can make this to happen. It is said that the use of the setState call back could be cumbersome but if there is a good understanding about composition of two functions then this should not be.
setState is asynchronous... so it is important to not make assumptions on sequentiality for two ops like:
this.setState({stateA : a})
this.setState({stateB : b})
The only way to "force" sequentiality through setState is through its call back:
this.setState({ .... }, () => {do after setState is done})
Somehow this is what you need to follow i.e. at the setState you are using inside findEmployeID it is necessary to do something like:
const self = this;
this.setState({ ..... }, () => {self.createQuestions()})
Whoever placed that negative better explain his reason. The .then part of the fetch does not guaranty sequentiality so it falls to the situation similar where two setStates are executed one after the other. A wait also does not guaranty sequentiality.

Test the status code of a real request to an API with Jest

Hello I'm trying to test this API call but I don't know how to test for the status code of the response since it is a real (and it has to stay like that) API call and not a mock one
this is the function I'm testing:
export const getDataFromApi = (url) => {
return axios.get(url)
.then(({ data }) => data)
.catch(err => console.log(err.toString()));
}
and this is the test:
describe('Read data from API', () => {
test('Get result of the API call', (done) => {
const apiUrl = "https://rickandmortyapi.com/api/character";
getDataFromApi(apiUrl)
.then(data => {
expect(data).toBeDefined();
expect(data.results.length).toBeGreaterThan(0);
done();
});
});
});
how can I expect if the status code of data is 200 or if is another status code?
also is necessary for me to leave that done after the execution of the function? I know with call backs I have to put it but with this promise I'm not sure
Axios has a single response object returned in both the success and error paths which contains the HTTP status code. An error is raised if the response is not in the 2xx range.
You can plumb the status code as a return object from your getDataFromApi() wrapper function, but you'll probably want the full response object for other checks (like headers). I recommend getting rid of the wrapper altogether.
Without the wrapper, here's 2 different status checks using promises, one for success and one for failure:
describe('Read data from API', () => {
test('Get successful result of the API call', async() => {
const apiUrl = "https://rickandmortyapi.com/api/character";
await axios.get(apiUrl)
.then(r => {
expect(r.data).toBeDefined();
expect(r.data.results.length).toBeGreaterThan(0);
expect(r.status).toBeGreaterThanOrEqual(200);
expect(r.status).toBeLessThan(300);
})
.catch(e => {
fail(`Expected successful response`);
});
});
test('Get failure result of the API call', async() => {
const apiUrl = "https://rickandmortyapi.com/api/character-bad";
await axios.get(apiUrl)
.then(r => {
fail(`Expected failure response`);
})
.catch(e => {
if (e.response) {
expect(e.response.status).toBeGreaterThanOrEqual(400);
expect(e.response.status).toBeLessThan(500);
} else {
throw e;
}
});
});
});

Show loading spinner before axios fetches data using .get

When a user lands on their dashboard I want to load some widgets and I will be doing it via axios. I want to show a loading spinner while the data is being fetched. After some digging it seems like the way to do this is by using axios interceptors. (I think) It looks like I have it working but I don't know where I should be handling the response as doing it both ways works.
Here is the first way which works:
axios.interceptors.request.use((config) => {
console.log('Start Ajax Call');
FreezeUI();
return config;
}, (error) => {
console.log(error);
return Promise.reject(error);
});
axios.interceptors.response.use((response) => {
console.log('Done with Ajax call');
document.querySelector('.test').insertAdjacentHTML('afterbegin', response.data.html);
UnFreezeUI();
return response;
}, (error) => {
return Promise.reject(error);
});
axios.get('/account/active-listings')
.then(response => {
// Do I need this?
})
.catch(err => console.log(err));
And the second way that also works. But, it doesn't seem like I actually need that .then() and .catch() block at all?
axios.interceptors.request.use((config) => {
console.log('Start Ajax Call');
FreezeUI();
return config;
}, (error) => {
console.log(error);
return Promise.reject(error);
});
axios.interceptors.response.use((response) => {
console.log('Done with Ajax call');
return response;
}, (error) => {
return Promise.reject(error);
});
axios.get('/account/active-listings')
.then(response => {
document.querySelector('.test').insertAdjacentHTML('afterbegin', response.data.html);
UnFreezeUI();
})
.catch(err => console.log(err));
I'm not sure if I got it right, but what I think you are looking for is the onDownloadProgress option which you can add in your request config.
it is a function which you can implement which receives a progressEvent.
In that function you could set the spinner.
Take a look at the request config part on their github page
small example for clarity:
axios.get('/account/active-listings', {
onDownloadProgress: (pe) => document.querySelector('.place-to-insert-spinner').insertAdjacentHTML(loading spinner thingie)
})
EDIT: You probably should remove the spinner when your request is finished too.

Fetch using cached data when no internet connection - Javascript - React

I have a webapp that needs to use cached data when there's no internet connection. I have it working well now using a second fetch call inside the catch block but I feel this isn't the right approach.
fetch(api)
.then(resp => resp.json())
.then(json => {
this.setState({
result: json.Results,
})
})
.catch(e => {
const options = {
cache: "force-cache"
}
fetch(api, options)
.then(resp => resp.json())
.then(json => {
console.log(`failed to fetch --- using cached data`)
this.setState({
result: json.Results,
})
})
.catch(e => {
console.error("Insufficient data")
})
})
Is there a better way to go about this?
Checking for navigator.onLine was an easy conditional to avoid any issues.
https://davidwalsh.name/detecting-online

Need guidance! Trying to learn about fetch() and Promises

Basically I'm trying to fetch the URL and URLPaths for two images I've uploaded (to Firebase) using the firebase function /storeImage and JSON.Stringify().
Below is the snippet of code that enables me to fetch data for the ONE image.
.then(token => {
authToken = token;
return fetch("myappURL/storeImage",
{
method: "POST",
body: JSON.stringify({
image: image.base64
}),
headers: {
Authorization: "Bearer " + authToken,
}
});
})
.catch(err => {
console.log(err);
alert("Oops! Something went wrong, please try again1")
dispatch(uiStopLoading());
})
.then(res => {
if (res.ok) {
return res.json();
} else {
throw(new Error());
}
})
.then(parsedRes => {console.log(parsedRes);
Now I want to fetch data from a second image.
What I gather, from the docs I've read, is that I should use promises for multiple async calls like what I have above. So, shouldn't something like this (see below) work?
.then(token => {
authToken = token;
let image = fetch(... image: image.base64 ...);
let coverImage = fetch(... coverImage: coverImage.base64 ...);
Promise.all([image, coverImage])
.then(ress => { ress.forEach(
res => {
process( res.json() );
})
})
.catch(err => {...})
.then(res => {...})
.then(parsedRes => {console.log(parsedRes);)
Spoiler alert. I tried and it didn't. But I cannot understand why.
When you chain promises together, that is, start a new promise inside a then callback you need to return it.
Promise.all returns a single new promise that resolves when all of the promises passed to it resolve. In your code above you're neglecting to return it.
E.g. Try running this code which logs undefined
Promise.resolve()
.then(() => {
Promise.all([Promise.resolve(1), Promise.resolve(2)])
})
.then(result => console.log(result))
vs this code which logs [1, 2]
Promise.resolve()
.then(() => {
return Promise.all([Promise.resolve(1), Promise.resolve(2)])
})
.then(result => console.log(result))

Categories