Difference between try/catch vs then/catch with axiom - promise

Trying to understand what is difference between these all with respect to axios library.
function doSomething() {
axios.get(url)
.then((response) => process(response))
.catch((error) => handle(error))
}
vs
async function doSomething() {
try {
const response = await axios.get(url);
process(response);
} catch(error) {
handle(error);
}
}
vs
async function doSomething() {
return await axios.get(url);
}
vs
function doSomething() {
return axios.get(url);
}
Trying to understands this and write wrapper for axios calls for the consumer.
Thanks.

Related

Fetching asynchronous data in a lit-element web component

I'm learning how to fetch asynchronous data in a web component using the fetch API and lit-element:
import {LitElement, html} from 'lit-element';
class WebIndex extends LitElement {
connectedCallback() {
super.connectedCallback();
this.fetchData();
}
fetchData() {
fetch('ajax_url')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
};
response.json();
})
.then(data => {
this.data = data;
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
}
render() {
if (!this.data) {
return html`
<h4>Loading...</h4>
`;
}
return html`
<h4>Done</h4>
`;
}
}
customElements.define('web-index', WebIndex);
However the html rendered never changes. What I'm doing wrong? Is this the best way to fetch asynchronous data in a web component?
You need to register data in component properties so that the render is called once value of data is changed
static get properties() {
return {
data: Object
}
}
https://lit-element.polymer-project.org/guide/properties

How can i return rejected from async-await?

I would like to return rejected, when fetch request is fail. How can i reject async await?
class FetchUrl {
static async getJson(api) {
try {
const response = await fetch(api);
if (response.ok) {
const questions = await response.json();
return questions;
}
} catch (error) {
throw new Error("Request Failed!");
}
}
}
FetchUrl.getJson(this.api).then((resolved) => {
console.log(resolved)
// this sampe of code is executing even fetch is rejected.. what can i do
to avoid it?
}, rejected => {
console.log(rejected)
})
}

Using Async/Await with Knex migrations

I am using Knex migrations with regular promise methods, like this:
exports.up = function (knex) {
return knex.schema
.hasTable('table_name')
.then(function (exists) {
if (!exists) {
return knex
.schema
.createTable('table_name', function (table) {
table.increments('id').primary();
})
.then(console.log('created table_nametable'));
}
});
};
How would I refactor this to use async/await? The overall structure, where we are returning knex.schema with a chain of promise methods is throwing me for a loop.
something like this should do:
exports.up = async function (knex) {
if (! (await knex.schema.hasTable('table_name')) ) {
await knex.schema.createTable('table_name', function (table) {
table.increments('id').primary();
});
}
// awaiting sequentially multiple promises to resolve one by one
for (let item of arrayOfStuffToAwait) {
await item;
}
}
exports.down = async function (knex) {
await knex.schema.dropTable('table_name');
}

Set the sequence of execution of asynchronous dispatch (redux\redux-saga)

I need to perform an asynchronous request. To do this, I'm debating a preloader, then I make a request, then I want to stop the preloader. The console should have: "show loader, load-app, hide loader", and output "show loader, hide loader, loading-app". How to save a sequence of calls?
How set the sequence of execution of asynchronous dispatch (redux\redux-saga)?
import { showLoader, hideLoader } from '../../reducer1'
import { authorizeToken } from '../reducer2'
async componentDidMount() {
const { dispatch } = this.props
const tokenLS = localStorage.getItem('token')
await dispatch(showLoader()); //show loader
await dispatch(authorizeToken(tokenLS)); // async request
await dispatch(hideLoader()); //hide loader
}
}
This code for Loader
import * as act from './actions'
const initialState = {
loadingPage: false
}
export const showLoader = () => {
console.log('show loader')
document.body.classList.add('loading-app')
return { type: act.startLoading }
}
export const hideLoader = () => {
console.log('hide loader')
document.body.classList.remove('loading-app')
return { type: act.finishLoading }
}
export default function loading(state = initialState, action) {
switch (action.type) {
case act.startLoading:
return { ...state, loadingPage: true }
case act.finishLoading:
return { ...state, loadingPage: false }
default:
return state
}
}
This code for async request:
function* authorizeWithToken({ payload: { token } }) {
try {
const { token:userToken } = yield call(authApi.authUserFromToken, token)
yield put({ type: AUTH_SUCCESS, payload: { token: userToken } })
yield console.log('end request')
} catch (error) {
throw new Error(`error request with token ${token}`)
}
}
export function* authorizeSaga() {
yield takeLatest(AUTH_REQUEST, authorize)
}
export function* authorizeWithTokenSaga() {
yield takeLatest(AUTH_REQUEST_TOKEN, authorizeWithToken)
}
This is reducer:
export const authorizeToken = (token) => ({
type: AUTH_REQUEST_TOKEN,
payload: {token}
})
I think there's some misunderstanding here. Your componentDidMount function does not need to by async. redux-saga enables you to move all async actions into sagas and out of the components. That way your components are easier to manage. I would change your componentDidMount to dispatch a single action and let your saga handle all the logic. Try changing it to this:
import { authorizeToken } from '../reducer2'
componentDidMount() {
const { dispatch } = this.props
const tokenLS = localStorage.getItem('token')
dispatch(authorizeToken(tokenLS)); // async request
}
Now in your saga, try this:
import { showLoader, hideLoader } from '../../reducer1'
function* authorizeWithToken({ payload: { token } }) {
try {
yield put(showLoader());
const { token:userToken } = yield call(authApi.authUserFromToken, token)
yield put({ type: AUTH_SUCCESS, payload: { token: userToken } })
yield put(hideLoader())
} catch (error) {
throw new Error(`error request with token ${token}`)
}
}
Now your saga will be in charge of displaying the loader, fetching the data, and hiding the loader. In that order.

InfiniteLoader and react-redux

Component InfiniteLoader from react-virtualised requires function passed as property loadMoreRows to have signature like { startIndex: number, stopIndex: number }): Promise.
I'm using redux in my project, so loadMoreRows is a redux action creator like this:
const fetchEntities(start, stop) {
return fetch(`${myUrl}&start=${start}?stop=${stop}`)
}
const loadMoreRows = ({ startIndex, stopIndex }) => {
return (dispatch, getState) => {
return function(dispatch) {
return fetchEntities(startIndex, stopIndex).then(
items => dispatch(simpleAction(items)),
error => console.log(error)
)
}
}
}
after that, this action is connected to react component containing InfiniteLoader using connect function from react-redux.
So I'm not sure, how can I satisfy signature requirement, as redux action creators don't return any value/
eyeinthebrick is correct. A Promise is not a required return value.
When you "connect" a Redux action-creator, invoking it (dispatching it) actually returns a Promise. So for example I think you could do something more like this...
function fetchEntities (start, stop) {
return fetch(`${myUrl}&start=${start}?stop=${stop}`)
}
const loadMoreRows = ({ startIndex, stopIndex }) => {
return async (dispatch, getState) => {
try {
const items = await fetchEntities(startIndex, stopIndex)
await dispatch(simpleAction(items))
} catch (error) {
console.log(error)
}
}
}
At which point InfiniteLoader can just await the returned Redux promise.

Resources