In my Ionic 2 project I am downloading data from server every 1 minute in a provider class, and whenever the new data comes I need to refresh a chart in my page class, how can I use observables to achieve that?
This is how the code looks like in simplified version:
let startTime = new Date(Math.ceil(new Date().getTime() / 60000) * 60000);
this.Source = Rx.Observable.timer(startTime, 60000).timeInterval().pluck('interval');
this.Subscription = this.Source
.subscribe(data => {
this.http.post(this.ConnectionString)
.map(res => res.json())
.subscribe(data => {
//code
});
});
You can try like this using Observable.interval
//Time in milleseconds
Observable.interval(15000).flatMap(x => this.http.post(this.ConnectionString))
.map(res => res.json())
.subscribe(data => {
//code
});
Related
I've got this part of code:
fetch(`https/someapi.com/data`)
.then(response => {
return response.json()
}).then(randomProduct => {
document.querySelector('#list').innerHTML = `
<span>${randomProduct.value}</span>
<button id="refresh-button" type="button">Refresh</button>
`;
var clickOnButton = document.querySelector("#refresh-button");
clickOnButton.addEventListener("click", () => {
})
})
How to I make this onClick event refresh the data the I read from API and display a new one?
first you need a button to make the fetch request
const fetchDataBtn = document.querySelector('#fetchdata')
const result = document.querySelector('#result')
// gets data from API and sets the content of #result div
const getData = function() {
result.innerText = 'Loading....'
fetch('https://dummyjson.com/products')
.then(res => res.json())
.then(data => {
result.innerText = JSON.stringify(data, null, 2)
})
.catch(error => console.log(error))
}
// add event listener for #fetchdata button
fetchDataBtn.addEventListener('click', getData)
const fetchDataBtn = document.querySelector('#fetchdata')
const result = document.querySelector('#result')
// gets data from API and sets the content of #result div
const getData = function() {
result.innerText = 'Loading....'
fetch('https://dummyjson.com/products')
.then(res => res.json())
.then(data => {
result.innerText = JSON.stringify(data, null, 2)
})
.catch(error => console.log(error))
}
// add event listener for #fetchdata button
fetchDataBtn.addEventListener('click', getData)
<button id="fetchdata">FETCH</button>
<div id="result"></div>
you can wrap it all in a function and call it like this
const fakeApi = () => new Promise(resolve => setTimeout(() => resolve({
value: Math.floor(Math.random() * 100)
}), 500))
const getData = () => fakeApi().then(randomProduct => {
document.querySelector('#main').innerHTML = `
<span>${randomProduct.value}</span>
<button id="refresh-button" type="button" onclick="getData()">Refresh</button>`
})
getData()
<div id="main"></div>
I'm not sure if I understood your question correctly, but from what I'be got you want to edit only the data on fetch no need to create a button and a listener every time. Place the fetch inside a dedicated function which is called onClick of the button in the fetch just edit the value.
I am able to get the API Response Time (duration) in the 'makeAPICall' function.
Now I need to pass it(the value of the duration variable)to another async function.
I am wondering if you could please provide the solution?
const makeApiCall = ClientFunction(() => {
console.time("timer1");
const testLocation = () => fetch('https://xxxxxx',
{method : 'GET',
headers:{
hash: 'xxxxx',
id: 'xxxxxxxxc'
}
})
.then(response => response.json())
.then(data => {
let duration = console.timeEnd("timer1");
console.log(duration);
});
return testLocation();
});
test('test', async t => {
await makeApiCall();
console.log(duration)?????
});
1st problem: console.timeEnd does not return anything, it print the ellapsed time to the console. Use performance.now() instead or just Date.
2)You should then return the duration from the last then.
const makeApiCall = ClientFunction(() => {
const start = new Date().getTime();
const testLocation = () => fetch('https://xxxxxx',
{method : 'GET',
headers:{
hash: 'xxxxx',
id: 'xxxxxxxxc'
}
})
.then(response => response.json())
.then(data => {
const end = new Date().getTime();
return end - start;
});
return testLocation(); // This returns a Promise<number>
});
test('test', async t => {
const duration = await makeApiCall();
console.log(duration)?????
});
You can try the following approach with the t.request method that TestCafe provides for API testing.
fixture `Test API`;
test('Simple Test', async t => {
const startTime = Date.now();
const response = await t.request('https://jsonplaceholder.typicode.com/comments');
const duration = Date.now() - startTime;
console.log(`request duration is ${duration}ms`); //request duration is 336ms
await t.expect(response.status).eql(200);
});
However, please note that a request's execution time will not be absolutely accurate because apart from execution of the request itself, the time required to process TestCafe's t.request command, the time for messaging and overhead costs will also be included in the measurement. You can use this measurement as a comparative estimate of the query execution time. Also, the timeout option is available.
I'm trying to learn exactly how to oversee the order in which my script runs using asynchronous functions and promises. At this point I've read/watched many information resources to try to get this right but something about my code just isn't working:
I have a generic vue.js object containing my methods, and running the series of functions asynchronously when the app is mounted:
var testAPP = new Vue({
el: '#test-app',
data: {
},
methods: {
fake_fetch: function () {
return new Promise((resolve) => {
setTimeout(() => {console.log("Returning fetch results."); resolve("good boy!")}, 10000)
})
},
first_step: function () {
console.log('Playing with my puppy!')
this.fake_fetch()
.then((data) => {
let praise = "Buddy is a " + data
console.log(praise)
return ("nap.")
})
.then((data) => {
return new Promise((resolve) => {
setTimeout(() => {console.log("Phew! We are taking a " + data); resolve(true)}, 20000)
})
})
},
second_step: function () {
console.log('Baking some cookies!')
this.fake_fetch()
.then((data) => {
data = data.replace(" ", ", ")
let praise = "Oh man these are " + data
console.log(praise)
return ("nap.")
})
.then((data) => {
return new Promise((resolve) => {
setTimeout(() => {console.log("I'm so full, I'm taking a " + data); resolve(true)}, 20000)
})
})
},
third_step: function () {
console.log('Putting out a hit on Polly')
this.fake_fetch()
.then((data) => {
let praise = "The job was a success? You did " + data
console.log(praise)
return ("nap.")
})
.then((data) => {
return new Promise((resolve) => {
setTimeout(() => {console.log("A moment of silence for Polly as he takes a dirt " + data); resolve(true)}, 20000)
})
})
},
get_started: function () {
v = this
async function my_day(v) {
const task_one = await v.first_step()
const task_two = await v.second_step()
const task_three = await v.third_step()
return ([task_one, task_two, task_three])
}
my_day(v).then((data) => {
if (false in data) {
return ("Something went wrong.")
} else {
return ("My day is done, time to rest... again.")
}
})
},
},
mounted: function () {
this.get_started()
}
})
The result I expect to get based on the order I 'thought' would be correct is this:
Playing with my puppy!
Returning fetch results.
Buddy is a good boy!
Phew! We are taking a nap.
Baking some cookies!
Returning fetch results.
Oh man these are good, boy!
I'm so full, I'm taking a nap.
Putting out a hit on Polly
Returning fetch results.
The job was a success? You did good boy!
A moment of silence for Polly as he takes a dirt nap.
My day is done, time to rest... again.
Ignoring the silliness of the output statements, thats the order they should appear. My current code gives me this:
Playing with my puppy!
Baking some cookies!
Putting out a hit on Polly
My day is done, time to rest... again.
Returning fetch results.
Buddy is a good boy!
Returning fetch results.
Oh man these are good, boy!
Returning fetch results.
The job was a success? You did good boy!
Phew! We are taking a nap.
I'm so full, I'm taking a nap.
A moment of silence for Polly as he takes a dirt nap.
The first four lines come up right away which doesn't feel right as there should be my built in delays stalling each 'step' function before the next one fires.
I've tried many things from making 'my_day()' its own function within methods and calling it via this.my_day() but that didn't make a difference. I've tried playing around with different return statements on the promises as well as making each following step function dependent on the variable of its predecessor but these resulted in the same functionality.
Why are my functions starting at the same time and not following the 'order' I have built into my async function?
Thank you for any help!
Also the html I used to run this in Edge is simple, I was just interested in the console:
<!DOCTYPE html>
<script src="https://unpkg.com/vue#2.6.10/dist/vue.min.js"></script>
<script type="text/javascript" src="C:\Users\adarwoo\Documents\Python Scripts\JS\async2.js"></script>
You are using await, but there is no async
first_step: async function() { // <-- async needed
console.log('Playing with my puppy!')
return this.fake_fetch() // <-- return needed
.then((data) => {
let praise = "Buddy is a " + data
console.log(praise)
return ("nap.")
})
.then((data) => {
return new Promise((resolve) => {
setTimeout(() => {
console.log("Phew! We are taking a " + data);
resolve(true)
}, 20000)
})
})
}
I am creating a search page, to search for some data on keyup, for each keyup a API being called, but I want to stop the previous call if 2nd API being called.
myFunction(term) {
const controller = new AbortController();
const signal = controller.signal;
controller.abort();
var apiUrl = window.BASE_URL + '/search?param=' + term;
console.log(apiUrl);
this.setState({
searching: true
});
return fetch(apiUrl, { credentials: 'include', signal: signal })
.then(this.handleErrors)
.then(response => response.json())
.then(responseJson => {
console.log(responseJson);
})
.catch(error => {
console.error(error);
});
}
An example to cancel previous fetch requests:
const controller = useRef<AbortController>() // useRef: for function component.
// You can create a property in a class component to store this
// (e.g. `this.controller = null` in your constructor)
function fetchAndAbortPrevious() {
controller.current?.abort()
controller.current = new AbortController()
fetch('https://cat-fact.herokuapp.com/facts', {
signal: controller.current.signal,
})
.then((response) => response.json())
.then((response) => console.log(response))
.catch((err) => console.log('error: ', err))
}
You already providing the signal to the fetch call, but since you initialised it inside your function scope, the outer world has no reference to it, so it can't be used.
So f.ex. pass it as a param to your function:
const controller = new AbortController();
const signal = controller.signal;
myFunction(term, signal) { ... }
Then whenever needed call abort:
signal.abort()
Also be sure you are not using IE as it is not supported on that browser.
Other option to store signal object outside and reinitialise it when myFunction is called:
signal;
myFunction(term) {
this.signal ? signal.abort() : false;
const controller = new AbortController();
this.signal = controller.signal;
< ... >
}
I'd like to hit and display every 5 seconds from a http link, and it seems to be that using angular2, an observable would be the way to go?
getPhaseVotes(issue: string) {
return this.http.get(this.URL + 'issue/' + issue + '/getPhaseVotes')
.subscribe(data => this.phase_votes = data.json(),
err => console.log(err),
() => this.getStatus(issue));
}
How should I be updating this every 5 seconds?
You could use the interval operator of Observable:
#Injeactable()
export class SomeService {
constructor(private http:Http) {}
getPhaseVotes(issue: string) {
return Observable.interval(5000).flatMap(() => {
return this.http.get(this.URL + 'issue/' + issue + '/getPhaseVotes')
.map(res => res.json());
});
}
}
This way you need to call once the getPhaseVotes method and subscribe on it. Every 5 seconds, an HTTP request will be executed transparently and the result provided within the subscribed callback:
#Component({
(...)
})
export class SomeComponent {
constructor(private service:SomeService) {
this.service.getPhaseVotes('someissue')
.subscribe(data => this.phase_votes = data,
err => console.log(err),
() => this.getStatus(issue));
}
}
This article could give you more hints in its "Polling" section:
https://jaxenter.com/reactive-programming-http-and-angular-2-124560.html