I have the following code, using async - await... that works in HTML + JavaScript environment, except if I use it inside EXTJS App, component listener.
...
onListInitialize: function(component, eOpts)
{
const citiesRef= db.collection("cities");
// defining async function
async function getIsCapitalOrCountryIsItaly() {
const isCapital = citiesRef.where('capital', '==', true).get();
const isItalian = citiesRef.where('country', '==', 'Italy').get();
const [capitalQuerySnapshot, italianQuerySnapshot] = await Promise.all([
isCapital,
isItalian
]);
const capitalCitiesArray = capitalQuerySnapshot.docs;
const italianCitiesArray = italianQuerySnapshot.docs;
const citiesArray = capitalCitiesArray.concat(italianCitiesArray);
return citiesArray;
}
//We call the asychronous function
getIsCapitalOrCountryIsItaly().then(result => {
result.forEach(docSnapshot => {
console.log(docSnapshot.data());
});
});
}
...
I'm getting the error: Expected an assigment or function call and instead saw an expression.
I tried Ext.Promise without success.
SOLVED! Using one promise for each query.
Sample of code:
Ext.Promise.all([
new Ext.Promise(function(resolve, reject) {
setTimeout(function() {
resolve('one');
}, 5000);
}),
new Ext.Promise(function(resolve, reject) {
setTimeout(function() {
resolve('two');
}, 4000);
})
])
.then(function(results) {
console.log('first function result', results[0]);
console.log('second function result', results[1]);
Ext.Msg.alert('Success!', 'All promises returned!');
});
Related
When I mock a get using MockAdapter and reply with a Promise, the promise is evaluated fine and I'm able to select the response data.
When I try the same thing with a Post, it doesn't work. The .then method isn't evaluated and I don't get the response data.
test:
var axios = require("axios");
var MockAdapter = require("axios-mock-adapter");
let mock;
beforeAll(() => {
mock = new MockAdapter(axios);
});
afterEach(() => {
mock.reset();
});
test("", async () => {
const response = { data: { assignee: '' }};
mock.onPost(`${APP_ROOT}/${ASSIGN}`).reply(function (config) {
return new Promise(function(resolve, reject) {
setTimeout(function () {
resolve([200, response]);
}, 1000);
});
})
})
useEffect in page:
useEffect(() => {
assign(id)
.then(responseData => {
})
.catch(error => {
})
}
I've got a very similar test using mock.onGet returning a Promise and everything works fine. Is there a reason why this shouldn't work for a Post?
I've tried various url's on the Post. For the onGet, I leave it blank but haven't seen any onPost examples with this - is onPost() with no url legal?
In case it matters, I've also set up a localStorage mock.
I'm having trouble trying to get an async await to work inside a for loop when using createAsyncThunk. I expected that dispatch(performRunAllCells()) will call the API updateBrowser() synchronously for each cell in the editor.cells array in order. Instead, the dispatch resulted in updateBrowser() being called asynchronously all at once. What is happening here?
export const performRunAllCells = createAsyncThunk(
'editor/runAllCells',
async (_, { dispatch, getState, rejectWithValue }) => {
const { notebook: { selectedDataset } } = getState() as {notebook: {selectedDataset: string}};
const { editor } = getState() as {editor: EditorState};
try {
let results: DataEntity | undefined;
for (const cell of editor.cells) {
dispatch(setCellStatus({ id: cell.id, execStatus: '*' }));
results = await updateBrowser(selectedDataset, cell.editorContent);
dispatch(setCellStatus({ id: cell.id }));
}
return results;
} catch (e) {
return rejectWithValue(e.response.data);
}
},
);
Edit
Currently I'm testing updateBrowser() with a setTimeout:
export async function updateBrowser(selectedDataset: string, editorContent: string): Promise<DataEntity> {
return new Promise((resolve) => {
setTimeout(() => {
console.log('test');
resolve({
raw: editorContent, html: 'Test', console: 'Test',
});
}, 3000);
});
}
I was able to know if it's synchronous/asynchronous through the console log above. Currently, it is printing multiple "test" at once.
Nevermind. I made a mistake somewhere else and the code wasn't actually being called. It is working now after fixing it.
I am trying to mock a simple function that uses fetch. The function in question looks like this:
export const getPokemon = async () => {
//function that makes the API call and fetches our pokemon
//getPokemon.js
const randomId = () => Math.floor(Math.random() * 151 + 1);
const pokemonApiUrl = `https://pokeapi.co/api/v2/pokemon/`;
export const getPokemon = async () => {
//function that makes the API call and fetches our pokemon
const id = randomId();
let pokemon = { name: "", image: "" };
try {
const result = await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`);
console.log(result)
const data = await result.json();
pokemon.name = data.name;
pokemon.image = data.sprites.other["official-artwork"].front_default;
return pokemon;
} catch (err) {
console.error(err);
Whenever I try to mock the function in my unit tests I receive back a TypeError: Cannot read property 'json' of undefined. Basically, the result comes back as undefined and thus we cannot call our .json(). It works fine in production and the fetch calls work as expected. I am using React Testing Library and Jest.
I have tried to replaced the global fetch in the following manner:
//PokemonPage.test.js
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ data: { name: 'Charizard' } }),
})
);
I've also tried to create a fakeFetch and send it in to my function as a dependency injection, but I get the exact same error.
Lastly, I've tried to install jest-fetch-mock but yet again I am getting the same error... Has anyone encountered the same thing?
The failing function gets called in production here:
function Pokemon({ pokemonTrainer }) {
...
useEffect(() => {
async function fetchData() {
pokemonRef.current = await getPokemon();
setPokemonList((prev) => [
...prev,
{ name: pokemonRef.current.name, image: pokemonRef.current.image },
]);
}
fetchData();
}, []);
...
}
I make an api call to an endpoing and inside the apiFetch I get a value. I want to display this value from outside the function but it doesn't get updated. Any ideas why it does this?
save: () => {
var newValue="default";
apiFetch( { path:'/url', } ).then( res => {
newValue = (res[0].value);
// this shows the new value
console.log(newValue);
} );
//this shows "default"
return <p>{newValue}</p>
}
Your function is asynchronous, you can use async/await
save: async () => {
const response = await apiFetch( { path:'/url', } );
const newValue = response[0].value;
console.log(newValue);
return <p>{newValue}</p>
}
Then, inside your caller block:
const newValueParagraph = await yourobject.save();
It looks like you need to return your Promise. Right now you make the async request to the api, and while that's doing it's thing you return newValue which is still just 'default.
Try like this:
save: () => {
var newValue = "default";
return apiFetch({ path: '/url', }).then(res => {
newValue = (res[0].value);
// this shows the new value
console.log(newValue);
return <p>{newValue}</p>
});
}
I am using a promise based hook in a React app to fetch async data from an API.
I am also using a Axios, a promise based http client to call the API.
Is it an anti-pattern to use a promise based client inside another promise? The below code does not seem to work.
const getData = () => {
return new Promise((resolve, reject) => {
const url = "/getData";
axios.get(url)
.then(function(response) {
resolve(response);
})
.catch(function(error) {
reject(error);
});
});
const useAsync = (asyncFunction) => {
const [value, setValue] = useState(null);
const execute = useCallback(() => {
setPending(true);
setValue(null);
setError(null);
return asyncFunction()
.then(response => setValue(response))
.catch(error => setError(error))
.finally(() => setPending(false));
}, [asyncFunction]);
useEffect(() => {
execute();
}, [execute]);
return { execute, pending, value, error };
};
};
const RidesList = () => {
const {
pending,
value,
error,
} = useAsync(getData);
Oh man. I think you have a fundamental misunderstanding about how Promises work.
First, axios already returns a Promise by default. So your whole first function of getData can be reduced to:
const getData = () => {
const url = "/getData"
return axios.get(url)
}
But the meat of your code seems to indicate you want a querable Promise - so you can check the status of it for whatever reason. Here's an example of how you would do it, adapted from this snippet:
function statusPromiseMaker(promise) {
if (promise.isResolved) return promise
let status = {
pending: true,
rejected: false,
fulfilled: false
}
let result = promise.then(
resolvedValue => {
status.fulfilled = true
return resolvedValue
},
rejectedError => {
status.rejected = true
throw rejectedError
}
)
.finally(() => {
status.pending = false
})
result.status = () => status
return result
}
In this way, you can then do something like let thing = statusPromiseMaker(getData()) and if you look up thing.status.pending you'll get true or false etc...
I didn't actually run what's above, I may have forgotten a bracket or two, but hopefully this helps.
I have to admit - I haven't seen anything like this ever used in the wild. I am interested in knowing what you're actually trying to accomplish by this.
Axios itself returns a promise but if you want to make a custom class having your custom logic after each API call then you can use interceptors I was having the same requirement and this is how I am returning promises after applying my custom logic on each API call.
Interceptors will get executed separately after and before each request you made so we can simply use them if we want to modify our request or response.
here is my working solution have a look at it.
callApi = (method, endpoint, params) => {
this.apiHandler.interceptors.request.use((config) => {
config.method = method
config.url = config.baseURL + endpoint
config.params = params
return config
})
return new Promise((resolve, reject) => {
this.apiHandler.interceptors.response.use((config) => {
if (config.status == 200) {
resolve(config.data)
} else {
reject(config.status)
}
// return config
}, error => reject(error))
this.apiHandler()
})
}
Below is the code to call this function
helper.callApi("get", "wo/getAllWorkOrders").then(d => {
console.log(d)
})