Problem when calling the helper function - Vue - javascript

Main view:
<script>
import { testMethod1 } from "../helper";
export default {
methods: {
init(){
console.log("Res:", testMethod1());
}
}
}
</script>
Helper:
import DataService from "../services/data.service";
export function testMethod1() {
DataService.getByPage()
.then((response) => {
console.log(response)
return response;
})
.catch((error) => {
console.log(error);
})
}
Output:
From view:
Res: undefined
From helper:
0: {_id: "60b621b4809e4304e04e7df4", desc: "aaa", …}
1: {_id: "60b621b4809e4304e04e7df5", desc: "bbb", …}
(..)
What am I doing wrong?

// See this is the same error
const incorrectFoo = () => {
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => json)
}
const correctFoo = () => {
return fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => json)
}
const someOtherFoo = async () => {
console.log('incorrect foo', await incorrectFoo(), 'correctFoo', await correctFoo())
}
someOtherFoo()
This method is executing a async call,
export function testMethod1() {
DataService.getByPage()
.then((response) => {
console.log(response)
return response;
})
.catch((error) => {
console.log(error);
})
}
Now if you notice DatasService is a async call and that async call get to another context where it whenever get resolved returns response which mean testMethod1 is not returning anything any way try this
export function testMethod1() {
return DataService.getByPage()
.then((response) => {
console.log(response)
return response;
})
.catch((error) => {
console.log(error);
})
}
<script>
import { testMethod1 } from "../helper";
export default {
methods: {
async init(){
console.log("Res:", await testMethod1());
}
}
}
</script>

After importing the method from helper, you need also to declare it in methods section like:
<script>
import { testMethod1 } from "../helper";
export default {
methods: {
testMethod1, // this is same with testMethod1: testMethod1,
init(){
console.log("Res:", this.testMethod1());
}
}
}
</script>

Related

What if axios call in getServerSideProps() failed? How to repeat

I'm trying to pre render page using getServerSideProps in Next.js and everything works perfectly.
But what if the axios call failed due to server issue or Network error?
How can I repeat the call?
Here's my code:
export async function getServerSideProps() {
let ImagesList = {};
await axios
.get("https://www.*****.com/api/home")
.then((response) => {
if (response.data) {
ImagesList = response.data
}
})
.catch((err) => { });
return {
props: {
ImagesList,
}
}
}
you can try to wrap your axios call inside a while loop,
let result = false;
while(!result) {
await axios
.get("https://www.*****.com/api/home")
.then((response) => {
result = true
if (response.data) {
ImagesList = response.data
}
})
.catch((err) => { });
}

Synchrony - the second function starts before, the first function ends

I'm building a website in Javascript, and I have this problem:
I want to do something like that.
First function calls server X.
The second function also calls server X, but only after the first is completely finished.
func2afterFunc1 = async () => {
await func1Open();
await func2Use();
}
export const func1Open = () => (dispatch) => {
axios
.post('/callToFunc1', "")
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
};
//basically call to this function to signup
exports.callToFunc1 = (req, res) => {
serverX
.open()
.then((data) => {
console.log(data)
return res.status(201).json("wasOpen");
})
.catch((err) => {
console.error(err);
return res.status(500).json("error");
});
};
export const func2Use = (user) => {
return async (dispatch) => {
serverX
.useAfterOpened()
.then((data) => {
console.log(data);
})
.catch((err) => {
console.error(err);
});
}
}

Nativescript Vue - function is blocking DOM

I've got a nativescript vue application, and on a certain page I need to fetch some data (every 3 seconds) from an api using axios. The data is returned in xml, and I convert it to json using xml2js. I'm using async/await for both these functions. Something is blocking the UI thread, because whenever this function runs scrolling in my app freezes, along with any animations.
Does anyone know what here is blocking the DOM?
<template>
//ui code here
</template>
<script>
import { mapGetters } from 'vuex'
import axios from 'axios'
import xml2js from 'nativescript-xml2js'
export default {
name: 'component1',
data () {
return {
pending: true,
error: false,
results: null,
refreshInterval: null
}
},
computed: {
...mapGetters({
token: 'main/token'
})
},
methods: {
async requestData() {
const headers = {
Cookie: 'USER_ID=' + this.token
}
const url = 'url goes here'
const parser = new xml2js.Parser({
async: true
})
try {
const response = await axios.get(url, { headers: headers })
const newData = await new Promise((resolve, reject) => parser.parseString(response.data, (err, result) => {
if (err) reject(err)
else resolve(result)
}))
this.results = newData['results']
this.error = false
this.pending = false
} catch (e) {
this.data = null
this.error = e
this.pending = false
}
this.pending = false
}
},
created() {
setTimeout(() => {
this.requestData()
},500)
this.refreshInterval = setInterval(() => {
this.requestData()
},3000)
},
beforeDestroy () {
clearInterval(this.refreshInterval)
}
}
</script>
EDIT:
I tried implementing workers to offload xml2js to another thread, but still having the same issue. This is how my code looks now:
home.vue:
<template>
<template/>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'component1',
data () {
return {
dataLoaded: true,
error: false,
results: null,
refreshInterval: null
}
},
computed: {
...mapGetters({
token: 'main/token'
})
},
methods: {
requestData() {
console.log('fetching....')
this.$backendService
.api()
.then(xml => {
return this.$backendService.x2jworker(xml)
})
.then(json => {
if( this.results !== json['results'] ) {
this.results = json['results']
}
this.dataLoaded = true
this.error = false
})
.catch((error) => {
this.dataLoaded = true
this.error = true
})
}
},
created() {
setTimeout(() => {
this.requestData()
},500)
this.refreshInterval = setInterval(() => {
this.requestData()
},3000)
},
beforeDestroy () {
clearInterval(this.refreshInterval)
}
}
</script>
backend-service.js:
import axios from 'axios';
import xml2js from 'nativescript-xml2js'
import { WorkerService } from "../worker.service"
export default class BackendService {
api() {
return new Promise((resolve, reject) => {
const url = 'url'
axios.get(url)
.then(response => {
resolve(response.data)
})
.catch((error) => {
if (error) {
console.log('uh oh')
reject(error)
}
})
})
}
x2jworker(xml) {
return new Promise((resolve, reject) => {
var workerService = new WorkerService()
var jsWorker = workerService.initJsWorker()
jsWorker.onmessage = m => {
resolve(m.data)
}
jsWorker.postMessage(xml)
jsWorker.onerror = e => {
console.log(e)
jsWorker.terminate()
reject(e)
}
})
}
}
worker/javascript.worker.js:
import 'tns-core-modules/globals'
import xml2js from 'nativescript-xml2js'
global.onmessage = function (msg) {
console.log("Inside JS worker...")
var parser = new xml2js.Parser({
async: true
})
parser.parseString(msg.data, function (err, result) {
if (err) {
console.log(err)
global.close()
} else {
global.postMessage(result)
}
})
}
worker-service.js:
const workers = []
export class WorkerService {
constructor() {
}
initJsWorker() {
if (this.jsWorker) {
return this.jsWorker
}
const JsWorker = require("nativescript-worker-loader!./workers/javascript.worker.js")
this.jsWorker = new JsWorker()
workers.push(this.jsWorker)
return this.jsWorker
}
}
if ((module).hot) {
(module).hot.dispose(() => {
workers.forEach(w => {
w.terminate()
})
})
}

api call not working properly

I am trying to do a simple to do app that does a request to a pokemon api and send me the result.
like this:
<template>
<div id="app">
<div>{{pokemon.forms}}</div>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "app",
data() {
return {
pokemon: {}
};
},
methods: {
requestPokemon() {
return new Promise((resolve, reject) => {
axios.get("http://pokeapi.co/api/v2/pokemon/2").then(value => {
resolve(value);
})
.catch(error => {
reject(error);
})
});
}
},
beforeMount() {
this.requestPokemon().then(value => {
pokemon = value;
}).error(error => {
console.log(error);
})
}
};
</script>
<style>
</style>
the issue is that i get the following error:
Error in beforeMount hook: "TypeError: this.requestPokemon(...).then(...).error is not a function"
any help with this??
thanks
Replace error with catch, as the others said:
export default {
name: "app",
data() {
return {
pokemon: {}
};
},
methods: {
requestPokemon() {
return new Promise((resolve, reject) => {
axios.get("http://pokeapi.co/api/v2/pokemon/2").then(value => {
resolve(value);
})
.catch(error => {
reject(error);
})
});
}
},
beforeMount() {
this.requestPokemon().then(value => {
pokemon = value;
}).catch(error => {
console.log(error);
})
}
};
Your beforeMount is not correct.
As oMiKeY said in his answer, you need to change .error to .catch
You also need to bind the response to this.pokemon (and not just pokemon)
Then, as requestPokemon function returns a Promise, you need to find the data in it :
beforeMount() {
this.requestPokemon().then(value => {
this.pokemon = value.data
}).catch(error => {
console.log(error);
})
}

Unable to write Redux tests for action creators

ORIGINAL QUESTION
I'm following the example for writing tests for async action creators spelled out in the Redux documentation. I'm following the example as closely as possible, but I can't get the test to work. I'm getting the following error message:
TypeError: Cannot read property 'then' of undefined
(node:789) UnhandledPromiseRejectionWarning: Unhandled promise rejection
(rejection id: 28): TypeError: Cannot read property 'data' of undefined
Here is the code for my action creator and test:
actions/index.js
import axios from 'axios';
import { browserHistory } from 'react-router';
import { AUTH_USER, AUTH_ERROR, RESET_AUTH_ERROR } from './types';
const API_HOST = process.env.NODE_ENV == 'production'
? http://production-server
: 'http://localhost:3090';
export function activateUser(token) {
return function(dispatch) {
axios.put(`${API_HOST}/activations/${token}`)
.then(response => {
dispatch({ type: AUTH_USER });
localStorage.setItem('token', response.data.token);
})
.catch(error => {
dispatch(authError(error.response.data.error));
});
}
}
export function authError(error) {
return {
type: AUTH_ERROR,
payload: error
}
}
confirmation_test.js
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import * as actions from '../../src/actions';
import { AUTH_USER, AUTH_ERROR, RESET_AUTH_ERROR } from
'../../src/actions/types';
import nock from 'nock';
import { expect } from 'chai';
const middlewares = [ thunk ];
const mockStore = configureMockStore(middlewares);
describe('Confirmation_Token action creator', () => {
afterEach(() => {
nock.cleanAll()
});
it('dispatches AUTH_USER', (done) => {
nock('http://localhost:3090')
.put('/activations/123456')
.reply(200, {
token: 7891011
});
const expectedActions = { type: AUTH_USER };
const store = mockStore({});
return store.dispatch(actions.activateUser(123456))
.then(() => { // return of async actions
expect(store.getActions()).toEqual(expectedActions);
done();
});
});
});
UPDATED QUESTION
I've partially (though not entirely) figured this out. I got this to work by adding a return statement in front of axios and commenting out the localstorage.setItem call.
I also turned the object I assigned to expectedActions to an array, and changed my assertion from toEqual to to.deep.equal. Here is the modified code:
actions/index.js
export function activateUser(token) {
return function(dispatch) { // added return statement
return axios.put(`${API_HOST}/activations/${token}`)
.then(response => {
dispatch({ type: AUTH_USER });
// localStorage.setItem('token', response.data.token); Had to comment out local storage
})
.catch(error => {
dispatch(authError(error.response.data.error));
});
}
}
confirmation_test.js
describe('ConfirmationToken action creator', () => {
afterEach(() => {
nock.cleanAll()
});
it('dispatches AUTH_USER', (done) => {
nock('http://localhost:3090')
.put('/activations/123456')
.reply(200, {
token: 7891011
});
const expectedActions = [{ type: AUTH_USER }];
const store = mockStore({});
return store.dispatch(actions.activateUser(123456))
.then(() => { // return of async actions
expect(store.getActions()).to.deep.equal(expectedActions);
done();
});
});
});
But now I can't test localStorage.setItem without producing this error message:
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called
in this test.
Is this because I need to mock out localStorage.setItem? Or is there an easier solve that I'm missing?
I figured out the solution. It involves the changes I made in my updated question as well as adding a mock of localStorage to my test_helper.js file. Since there seems to be a lot of questions about this online, I figured perhaps my solution could help someone down the line.
test_helper.js
import jsdom from 'jsdom';
global.localStorage = storageMock();
global.document = jsdom.jsdom('<!doctype html><html><body></body></html>');
global.window = global.document.defaultView;
global.navigator = global.window.navigator;
global.window.localStorage = global.localStorage;
// localStorage mock
function storageMock() {
var storage = {};
return {
setItem: function(key, value) {
storage[key] = value || '';
},
getItem: function(key) {
return key in storage ? storage[key] : null;
},
removeItem: function(key) {
delete storage[key];
}
};
}
actions.index.js
export function activateUser(token) {
return function(dispatch) {
return axios.put(`${API_HOST}/activations/${token}`)
.then(response => {
dispatch({ type: AUTH_USER });
localStorage.setItem('token', response.data.token);
})
.catch(error => {
dispatch(authError(error.response.data.error));
});
}
}
confirmation_test.js
describe('Confirmation action creator', () => {
afterEach(() => {
nock.cleanAll()
});
it('dispatches AUTH_USER and stores token in localStorage', (done) => {
nock('http://localhost:3090')
.put('/activations/123456')
.reply(200, {
token: '7891011'
});
const expectedActions = [{ type: AUTH_USER }];
const store = mockStore({});
return store.dispatch(actions.activateUser(123456))
.then(() => { // return of async actions
expect(store.getActions()).to.deep.equal(expectedActions);
expect(localStorage.getItem('token')).to.equal('7891011');
done();
});
});
});

Categories

Resources