Can't display from async function result - vue.js

I need to display in my html variable: {my_dates}. The problem that I can't get it work with fetch but can do with old ajax request.
not working code:
created: function(){
//this.getTableData()
url = 'http://dlang.ru/test'
async function fetchAsync () {
const response = await fetch(url);
return await response.json();
}
this.my_dates = fetchAsync();
}
Working code:
$.ajax({
url: "http://dlang.ru/test",
success: function (data) {
Vue.set(app, "my_dates", data);
app.show = true;
}
});

If you want to be able to assign result of fetchAsync() to this.my_dates then entire created hook method needs to be declared as async.
Then you also need await in front of fetchAsync call:
created: async function () {
const url = 'http://dlang.ru/test';
async function fetchAsync() {
const response = await fetch(url);
return await response.json();
}
this.my_dates = await fetchAsync();
}

Please try this:
created: function(){
//this.getTableData()
url = 'http://dlang.ru/test'
async function fetchAsync () {
const response = await fetch(url);
const data = await response.json();
Vue.set(app, "my_dates", data);
app.show = true;
}
fetchAsync();
}

Related

Jest does not continue after async method

I have an async method triggered by a click event where I make a call to an API and then process the response, like this:
async confirmName () {
const {name, description} = this.form;
const [data, error] = await Pipelines.createPipeline({name, description});
if (error) {
console.error(error);
this.serviceError = true;
return false;
}
this.idPipelineCreated = data.pipeline_id;
return true;
}
The test looks like this:
test("API success", async () => {
const ConfirmNameBtn = wrapper.find(".form__submit-name");
await ConfirmNameBtn.vm.$emit("click");
const pipelinesApi = new Pipelines();
jest.spyOn(pipelinesApi, "createPipeline").mockResolvedValue({pipeline_id: 100});
const {name, description} = wrapper.vm.form;
pipelinesApi.createPipeline().then(data => {
expect(wrapper.vm.pipelineNameServiceError).toBe(false);
wrapper.setData({
idPipelineCreated: data.pipeline_id
});
expect(wrapper.vm.idPipelineCreated).toBe(data.pipeline_id)
}).catch(() => {})
})
A basic class mock:
export default class Pipelines {
constructor () {}
createPipeline () {}
}
I'm testing a success API call and I mock the API call returning a resolved promised. The problem is the coverage only covers the first two lines of the method, not the part where I assign the response of the API call. Is this the correct approach?
Edit:
Screenshot of coverage report:
Don't mix up await and then/catch. Prefer using await unless you have very special cases (see this answer):
test("API success", async () => {
const ConfirmNameBtn = wrapper.find(".form__submit-name");
await ConfirmNameBtn.vm.$emit("click");
const pipelinesApi = new Pipelines();
jest.spyOn(pipelinesApi, "createPipeline").mockResolvedValue({pipeline_id: 100});
const {name, description} = wrapper.vm.form;
const data = await pipelinesApi.createPipeline();
expect(wrapper.vm.pipelineNameServiceError).toBe(false);
wrapper.setData({
idPipelineCreated: data.pipeline_id
});
expect(wrapper.vm.idPipelineCreated).toBe(data.pipeline_id)
expect(wrapper.vm.serviceError).toBe(false);
})

In reactnative expo I tried using secureStore from expo in redux to save token the one I get from api

I tried using redux to save token the one I get from api in react native ..its working now.
First one is for settoken and other one is for gettoken.
enter image description here
export const verifyOTP = (formValues, actions) => {
return async (dispatch) => {
dispatch(startSubmitting());
const url = `/validate-otp`;
var formdata = new FormData();
formdata.append("mobile", formValues.mobile);
formdata.append("otp", formValues.otp);
const response = await api.post(url, formdata);
dispatch({
type: "VERIFY_OTP",
payload: response,
});
dispatch(stopSubmitting());
await SecureStore.setItemAsync("userToken", response.data.access_token);
};
};
export const checkUser = () => {
return async (dispatch) => {
const token = await SecureStore.getItemAsync("userToken");
const url = `/me`;
const response = await api
.post(url, { token })
.then((res) => {
return res;
})
.catch((error) => {
return error.response;
});
dispatch({
type: "CHECK_USER",
payload: response,
});
};
};
The Problem
you are mixing two different implementations in checkUser to handle a promise which is clearly incorrect and leads to the issues.
The Solution
since your other parts of codes use the async/await so try to remove then/catch block from the response constant:
const checkUser = () => {
return async (dispatch) => {
const url = '/me';
try {
const token = await SecureStore.getItemAsycn("userToken);
const response = await api.post(url, {token})
dispatch({type: "CHECK_USER", payload: response})
} catch (error) {
// to proper action on failure case
}
}
}
Note 1: always use async/await in try/catch block. more on MDN documentation.
Optional
since you are trying to call two async actions (once for getting token and once for calling '/me' API), I encourage you to use two different try/catch blocks to handle the failure case for each async action separately. for example:
const checkUser = () => {
return async (dispatch) => {
let token = null;
try {
token = await SecureStore.getItemAsync("userToken");
} catch (err) {
// proper action in case of failure on getting the token from storage
}
// you may need to ignore API calls without the token, so:
try {
if(token){
const url = '/me';
const response = await api.post(url, {token});
dispatch({type: "CHECK_USER", payload: response});
}
} catch (err) {
// take proper action with the error response according to your applicaiton
}
}
}

How to return blob item from localForage in service worker?

in my service worker i store mp4 video in indexedDB with localforage library in a blob data. It's work ! but i don't know how can i return this blob data.
This is my fetchHandler code :
const fetchHandler = async (event) => {
const getResponse = async () => {
const request = event.request;
if( request.destination === 'video' ){
// Get from indexedDB
const value = await localforage.getItem('video');
// How return the video from indexedDB cache ?
if( value ) return value; // not working
// Add in indexedDB
var networkResponse = await fetch(event.request);
localforage.setItem('video', networkResponse.blob() ).then(function (value) {
// Do other things once the value has been saved.
console.log(value);
}).catch(function(err) {
// This code runs if there were any errors
console.log(err);
});
}else{
const openedCache = await caches.open(SW_CACHE_NAME);
const cacheResponse = await openedCache.match(request);
if (cacheResponse) return cacheResponse;
var networkResponse = await fetch(event.request);
const cachePutResponse = await openedCache.put(request, networkResponse.clone());
if (cachePutResponse) return cachePutResponse;
}
return networkResponse;
};
event.respondWith(getResponse());
};
thanks for your help
You need to pass a valid Response object to event.respondWith(). That entails a response body (which is what you get back from localforeage.getItem()), but also some response headers.
You can use the Response constructor to create that, and return it from your getResponse() function.
The code could look something like:
const value = await localforage.getItem('video');
if (value) {
// See https://fetch.spec.whatwg.org/#bodyinit for what's accepted
// as a BodyInit.
return new Response(value, {
headers: {
// Replace this with the actual MIME type for the video.
'content-type': 'video/mp4',
// Include any other headers here if desired.
}
});
}

Error loading preview in Firebase Storage

This is my function put
var metadata = {
contentType: 'image/png'
}
const task = fireStore.ref(fileName).put(uploadUri, metadata)
try {
await task
setUpLoading(false)
} catch(err) {
console.log(err)
}
but it didn't work.
Thanks for help.
I found solution for it.
let newImageUri
try {
const response = await fetch(imageUrl)
const blob = await response.blob()
await firebase.storage().ref().child(fileName).put(blob)
var ref = firebase.storage().ref().child(fileName).put(blob)
newImageUri = await ref.snapshot.ref.getDownloadURL()
} catch (error) {
console.log(error)
}

Where to check for token expiration and send refresh request

I have set up react-admin and am using it with the HydraAdmin component.
My login request returns a JWT and a refresh token. I store these in localStorage and want to check whether the JWT is expired before sending requests.
The problem is, where do I do that?
I tried the checkAuth function of my auth provider, but it isn't called before every fetch (e.g. POST).
I want to reliably be able to refresh my token before it's sent with a request.
Or is this not the right way to deal with this?
I solved it by adding my refreshToken function call to each data provider function.
Not sure if this is the right way to do this, but it worked.
My function to refresh the token:
function setAuth(auth) {
localStorage.setItem('token', auth.token);
localStorage.setItem('refreshToken', auth.refreshToken);
authHeaders.set("Authorization", `Bearer ${auth.token}`);
}
function getRefreshToken() {
return localStorage.getItem('refreshToken');
}
function getToken() {
return localStorage.getItem('token');
}
function isLoggedIn() {
return getToken() && getRefreshToken();
}
function isTokenExpired() {
const decoded = jwt_decode(getToken());
return decoded.exp < Date.now() / 1000 + 60 * 5;
}
function postRequest(route, body) {
return fetch(new Request(url(config.server, route), {
method: 'POST',
body: JSON.stringify(body),
headers: new Headers({ 'Content-Type': 'application/json' }),
}));
}
export async function refreshToken() {
if (!isLoggedIn()) {
return;
}
if (isTokenExpired()) {
const response = await postRequest(config.auth.refresh_route, {refreshToken: getRefreshToken()});
if (response.ok) {
setAuth(await response.json());
}
}
}
My data provider:
export const authHeaders = new Headers();
const fetch = (url, options = {}) => fetchHydra(url, {...options, headers: authHeaders });
const provider = hydraDataProvider(config.api, fetch);
class DataProvider {
async introspect() {
await refreshToken();
return provider.introspect();
}
async getList (resource, params) {
await refreshToken();
return provider.getList(resource, params);
}
async getOne (resource, params) {
await refreshToken();
return provider.getOne(resource, params);
}
async getMany (resource, params) {
await refreshToken();
return provider.getMany(resource, params);
}
async getManyReference (resource, params) {
await refreshToken();
return provider.getManyReference(resource, params);
}
async create (resource, params) {
await refreshToken();
return provider.create(resource, params);
}
async update (resource, params) {
await refreshToken();
return provider.update(resource, params);
}
async updateMany (resource, params) {
await refreshToken();
return provider.updateMany(resource, params);
}
async delete (resource, params) {
await refreshToken();
return provider.delete(resource, params);
}
async deleteMany (resource, params) {
await refreshToken();
return provider.deleteMany(resource, params);
}
}
export const dataProvider = new DataProvider();