How to call APi Service in component of Vue3 - vue.js

I am working on an application where I have created service js which I need to consume in different components of vue3. Here is my service code
const base_url = "https://localhost:7005/";
var apiObject = {
data: function() {
return {
response : undefined
};
},
methods: {
fetchContent: function(apiEndpoint) {
axios
.get(`${base_url}${apiEndpoint}`)
.then(res => {
this.response = res
})
.catch(e => {
this.errors.push(e);
});
}
}
};
Here is my component code. It is not working it gives me the error show in image below
<script>
import {fetchContent} from "../service/apiService";
export default {
data() {
return {
// url_base: "https://localhost:7005/api/weather/",
weather: undefined,
error : false,
errormessage : "",
searchHistory : []
};
},
methods : {
async fetchWeather(e) {
if (e.key == "Enter" && this.query) {
let {response} =await fetchContent(`api/weather/forecast?city=${query}`) //get(query,`${weather_url}forecast?city=`); //await axios.get(`${this.url_base}forecast?city=${this.query}`);
this.setResults(response.data);
}else if (e.key == "Enter" && !this.query){
this.error = true;
this.errormessage = 'Please enter name to search!';
}
},
setResults(res) {
if(res.isSuccessful === true){
this.error = false;
this.weather = res.response;
this.saveData(res.response)
}else{
this.weather = undefined;
this.errormessage = res.response;
this.error = true;
}
},
saveData(res){
this.searchHistory = JSON.parse(localStorage.getItem("SearchHistory"));
if(this.searchHistory == null){this.searchHistory = [];}
res.forEach(x => {
this.searchHistory.push(x);
});
localStorage.setItem("SearchHistory",JSON.stringify(this.searchHistory));
}
},
};
</script>
Image

Related

How to create generic service using Vue3 Js

I am working on an application where I am trying to implement common functions which will call an API endpoint here is my implementation using vue3.
Page
<script>
import httpService from "./services/HttpService.vue";
export default {
data() {
return {
weather: undefined,
error : false,
errormessage : "",
};
},
methods : {
async fetchWeather(e) {
if (e.key == "Enter" && this.query) {
let {response} =await get(query,`${weather_url}forecast?city=`); //await axios.get(`${this.url_base}forecast?city=${this.query}`);
this.setResults(response.data);
}else if (e.key == "Enter" && !this.query){
this.error = true;
this.errormessage = 'Please enter name to search!';
}
},
setResults(res) {
if(res.isSuccessful === true){
this.error = false;
this.weather = res.response;
}else{
this.weather = undefined;
this.errormessage = res.response;
this.error = true;
}
}
},
};
</script>
Service
<script>
import axios from "axios";
export default async function GenericService() {
async function get(query,url) {
try {
let response = await axios.get(`${base_url}${url}${this.query}`);
return response;
} catch (err) {
throw new Error(err);
}
}
}
</script>
GlobalUrl
<script>
export const ConstantBaseUrl = {
base_url: "https://localhost:7005/",
};
export const EndPointUrl = {
weather_url : "api/weather/"
}
</script>
Here I want to achieve is there must be a common method that will be used to send a get request to my backend API. My code is not working and I know I am I might be missing something or doing it the wrong way because I am totally new to Vue3.js.

react-native-track-player Play one song and stop / await user input implementation

I am trying to use react-native-track-player in my app. The functionality of my app requires that one audio track is played, and then it needs to await user input.
I have tried the following code however it leads to laggy and unpredictable behaviour. Is there a way to natively implement pause after each track?
useTrackPlayerEvents([Event.PlaybackTrackChanged], async event => {
if(!autoplay&&appStateVisible==='active'){
TrackPlayer.pause();
TrackPlayer.seekTo(0)
} else {
setAutoplay(false)
}
if (
event.type === Event.PlaybackTrackChanged &&
event.nextTrack !== undefined
) {
const track = await TrackPlayer.getTrack(event.nextTrack);
const currentTrack = await TrackPlayer.getCurrentTrack();
const {title, artist, artwork} = track || {};
console.log(track)
setTrackTitle(title);
setTrackArtist(artist);
setTrackArtwork(artwork);
setTrackNumber(currentTrack)
}
});
Here is my service.js that will run in background mode.
import TrackPlayer, { Event, State } from "react-native-track-player";
import { AppState } from "react-native";
import React, { Component, useState, useEffect, useRef } from "react";
let wasPausedByDuck = false;
var appState = null;
var autoplay = false;
const subscription = AppState.addEventListener("change", (nextAppState) => {
if (
appState &&
appState.match(/inactive|background/) &&
nextAppState === "active"
) {
console.log("App has come to the foreground!");
}
appState = nextAppState;
console.log("AppState service", appState);
});
module.exports = async function setup() {
TrackPlayer.addEventListener(Event.PlaybackTrackChanged, async () => {
if (!autoplay && appState === "background") {
await TrackPlayer.pause();
await TrackPlayer.seekTo(0);
} else {
autoplay = false;
}
});
TrackPlayer.addEventListener(Event.PlaybackState, (x) => {
});
TrackPlayer.addEventListener(Event.RemotePause, () => {
TrackPlayer.pause();
});
TrackPlayer.addEventListener(Event.RemotePlay, () => {
TrackPlayer.seekTo(0);
TrackPlayer.play();
});
TrackPlayer.addEventListener(Event.RemoteNext, async () => {
autoplay = true;
await TrackPlayer.skipToNext();
await TrackPlayer.play();
});
function isEven(x) {
return x % 2 == 0;
}
TrackPlayer.addEventListener(Event.RemotePrevious, async () => {
const currentTrack = await TrackPlayer.getCurrentTrack();
const playbackState = await TrackPlayer.getState();
const position = await TrackPlayer.getPosition();
const isPrompt = isEven(currentTrack);
if (playbackState === "playing") {
if (position > 2) {
TrackPlayer.seekTo(0);
} else {
if (currentTrack !== 0) {
if (!isPrompt) {
TrackPlayer.skipToPrevious();
} else {
TrackPlayer.skip(currentTrack - 2);
}
} else {
TrackPlayer.seekTo(0);
}
}
} else {
if (currentTrack !== 0) {
if (!isPrompt) {
autoplay = true;
TrackPlayer.skipToPrevious();
TrackPlayer.play();
} else {
autoplay = true;
TrackPlayer.skip(currentTrack - 2);
TrackPlayer.play();
}
} else {
TrackPlayer.seekTo(0);
TrackPlayer.play();
}
}
});
TrackPlayer.addEventListener(Event.RemoteDuck, async (e) => {
if (e.permanent === true) {
TrackPlayer.stop();
} else {
if (e.paused === true) {
const playerState = await TrackPlayer.getState();
wasPausedByDuck = playerState !== State.Paused;
TrackPlayer.pause();
} else {
if (wasPausedByDuck === true) {
TrackPlayer.play();
wasPausedByDuck = false;
}
}
}
});
};
In response to this question on the react-native-track-player support discord from answered by jspizziri, who suggested adding one track to the queue at a time. I implemented this using a playlist ref and index ref and essentially controlling the player externally.

Why is InterstitialAd not loaded after the first trigger?

I manage to get the first ad to show, but app crashed the next time I try to trigger an ad. And gives me this error: Error: InterstitialAd.show() The requested InterstitialAd has not loaded and could not be shown
In App.js
componentDidMount() {
const eventListener = interstitial.onAdEvent(type => {
if (type === AdEventType.LOADED) {
this.setState({
setLoaded: true,
});
}
});
interstitial.load();
eventListener();
}
showAds = () => {
interstitial.show();
// No advert ready to show yet
if (!this.state.loaded) {
console.log('null');
return null;
}
};
// This trigger is within another function
this.showAds();
I have a class component so I use ComponentDidMount instead of useEffect. Might that cause some troubles?
UPDATE:
this.state = {
loaded: false,
setLoaded: false,
Listener: null,
};
The above state is an attempt to redo
const [loaded, setLoaded] = useState(false);
constructor () {
super();
this.Listener=null
}
componentDidMount() {
this.Listener = interstitial.onAdEvent(type => {
if (type === AdEventType.LOADED) {
this.setState({
loaded: true,
});
}else if(type === AdEventType.CLOSED){
this.loadAd()
}
});
this.loadAd()
}
componentWillUnmount(){
if(this.Listener!==null){
this.Listener()
}
}
loadAd = () =>{
this.setState({
loaded: false,
});
interstitial.load();
}
showAds = () => {
if (!this.state.loaded) {
console.log('null');
return null;
}else{
interstitial.show();
}
};

how can i use async and await in action object in vuex?

I'm gonna use an API and take it off some information, I use async/ await in mutations but as you know it's not standard that we used async data in mutation, and we have to use it in actions but how we can do it?
here my vuex codes:
import axios from "axios";
const state = {
token: "hjOa0PgKqC7zm86P10F3BQkTuLsEV4wh",
posts: [],
pending: true,
error: false,
}
const mutations = {
async getDataFromApi(state) {
try {
const res = await axios.get(
`https://api.nytimes.com/svc/movies/v2/reviews/picks.json?api-key=${state.token}`
);
if (res.status == 200) {
state.posts = res.data;
state.error = false;
}
} catch (e) {
state.posts = null;
state.error = e;
}
state.pending = false;
},
};
const actions = {
showData({
commit
}) {
commit("getDataFromApi");
},
}
and here vuejs codes that I used in the component :
<script>
import { mapState } from "vuex";
export default {
name: "Home",
mounted() {
this.getDataFromApi();
},
computed: {
...mapState(["pending", "error", "posts"]),
},
methods: {
getDataFromApi() {
this.$store.dispatch("showData");
},
},
};
</script>
It works perfectly in mutation but for standards, how can use this in action instead of mutation?
Well, actually it is pretty similar to what you have done so far :
const mutations = {
getDataFromApi(state, data) {
state.posts = data;
state.error = false;
state.pending = false;
},
setError(state, error) {
state.error = error;
state.posts = null;
state.pending = false;
},
};
const actions = {
async showData({ commit }) {
try {
const res = await axios.get(
`https://api.nytimes.com/svc/movies/v2/reviews/picks.json?api-key=${state.token}`
);
if (res.status == 200) {
commit("getDataFromApi", res.data);
} else {
commit("setError", new Error("Something went wrong."));
}
} catch (e) {
commit("setError", e);
}
},
};

VUE : Updating store data after login

I'm having an issue where the store data "menus" is not updated after i do a login.
Appearantly.. the object "loggedInUser" is not sat before i call "getMenus".. I'm not sure what i'm doing wrong here...
PS! When debugging in chrome, i notice that loggedInUser is "null" when entering the api call (see api.js codesnippet).
Login.vue (method) :
methods: {
doLogin() {
this.errorMessage = '';
this.loading = true;
let userCredentials = {
'username': this.loginEmail,
'password': this.loginPassword
};
this.$store.dispatch('tryLogin', {
'login': this.loginEmail,
'password': this.loginPassword
}).then((response) => {
this.$store.dispatch('getMenus')
.then((response) => {
this.$router.push('/')
});
});
}
},
Menus.vue (same as /)
computed: {
menus() {
return this.$store.getters.menus
}
},
created() {
this.$store.dispatch('getMenus')
},
methods: {
viewMenu: function(item) {
console.log("=> View Menu : " + item.Name)
this.$router.push('/viewmenu/' + item.Id)
}
}
}
store.js (getMenus action AND tryLogin)
actions: {
getMenus({ commit, getters }) {
api.getMenus(getters.loggedInUser)
.then(menus => {
commit('UPDATE_MENUS', menus);
});
},
tryLogin({ commit }, credentials) {
api.tryLogin(credentials)
.then(loggedInUser => {
commit('LOGGED_IN_USER', loggedInUser);
});
},
api.js (getMenus function)
getMenus(loggedInUser) {
var hostname = 'http://myurl'
var config = {
headers: {
'Content-Type': 'application/json'
}
}
var endpointUrl = hostname + '/api/Menu/GetMenus';
if (loggedInUser != null){
endpointUrl = hostname + '/api/Menu/GetMenusForSubCompany/' + loggedInUser.encryptedsubcompanyid;
}
return axios.get(endpointUrl, config)
.then(response => response.data);
},
From your store.js snippet, it seems you forget to return the promise.