Keep clicking Refresh button until data appears - javascript

I have one page for uploading a file which will be processed by the server in the background. I then have a second page where it shows only files that have been processed, which can take anything up to 5 seconds.
At the moment the code I have does this
cy.visit('/')
cy.get('.busy-spinner').should('not.exist', { timeout: 10000 })
cy.contains('Submit file').click()
cy.get('[id="requestinputFile"]').attachFile('test-file.txt');
cy.contains('Upload').click()
cy.contains('.notifications', 'Your file has been uploaded', { timeout: 10000 })
cy.wait(5000)
cy.visit('/processed-files')
cy.get('[data-render-row-index="1"] > [data-col-index="1"]').contains(filename)
Sometimes the wait is far too long, sometimes it is not long enough. What I want to do is to go to /processed-files immediately and check if the row with my filename exists.
If it does then continue. Otherwise
Pause for 1 second
Click a specific button (to reload the data on the page)
Wait until .busy-spinner does not exist (the data has been reloaded)
Check if the row exists
If it does then pass, otherwise loop - but for a maximum of 30 seconds.
This pattern will be repeated in many places, what is the best way to achieve this?

Can you just wait on the filename?
cy.contains('[data-render-row-index="1"] > [data-col-index="1"]', filename,
{ timeout: 30_000 }
)
If the reload is needed to get the correct row entry, a repeating function is a possibility
function refreshForData(filename, attempt = 0) {
if (attempt > 30 ) { // 30 seconds with a 1s wait below
throw 'File did not appear'
}
// Synchronous check so as not to fail
const found = Cypress.$(`[data-render-row-index="1"] > [data-col-index="1"]:contains('${filename}')`)
if (!found) {
cy.wait(1_000)
cy.get('Reload button').click()
cy.get('Spinner').should('not.be.visible')
refreshForData(filename, ++attempt)
}
}
refreshForData(filename) // pass in filename, function can be globalized
// maybe also pass in selector?

You can create a recursive function in which you can check the presence of the file name by reloading the page for a maximum of 30 seconds. In case you find the file name you exit the function.
let retry = 0
function isElementVisible() {
if (retry < 15 && Cypress.$('[data-render-row-index="1"] > [data-col-index="1"]'):not(:contains('filename'))) {
//Increment retry
retry++
//wait 2 seconds
cy.wait(2000)
//Reload Page by clicking button
cy.click('button')
//Check busy spinner is first visible and then not visible
cy.get('.busy-spinner').should('be.visible')
cy.get('.busy-spinner').should('not.be.visible')
//Call the recursive function again
isElementVisible()
} else if (retry < 15 && Cypress.$('[data-render-row-index="1"] > [data-col-index="1"]'):contains('filename')) {
//Row found Do something
return
} else {
//It exceeded the required no. of retries and a max of 30 seconds wait
return
}
}
//Trigger the recursive function
isElementVisible()

Related

Postman Retry logic goes in infinite loop

I am using postman for testing my API.
One of the API which takes some time to process the data I have added a retry logic to try 3 times to check if the end points work fine.
The initial value of retryCount is 3 which is set in the few test before this test where retry is executed.
Below is the code:
let retryCount = pm.environment.get('retryCount');
let responseData = pm.response.json();
console.log(responseData.data.events.length);
console.log(retryCount);
if(responseData.data.events.length == 0 && retryCount > 0)
{
retryCount = retryCount - 1;
console.log(retryCount);
pm.environment.set('retryCount',retryCount);
postman.setNextRequest("GetEvents");
}
else
{
pm.environment.set('data-response',responseData.data);
}
After 3 retries it should stop. however, it goes in the infinite loop. The problem is occurring because the variable is always 3 when the next call happens it should reduce by 1 and eventually become 0.
what could be the reason that above code goes in infinite state.
You might be reseting the value some where in collection scripts or some where elese in your collection. Create a new variable and try, use below method :
pm.variables.get("retryCounter")===undefined ? pm.variables.set('retryCounter',3):null
let responseData = pm.response.json();
console.log(responseData.data.events.length);
retryCount = pm.variables.get("retryCounter");
console.log(retryCount);
if(responseData.data.events.length === 0 && retryCount > 0)
{
retryCount = retryCount - 1;
console.log(retryCount);
pm.variables.set('retryCounter',retryCount)
//this gives this request name , you don't have to hardcode
postman.setNextRequest(pm.info.requestName);
}
else
{
pm.environment.set('data-response',responseData.data);
}
Try this code , here we are using pm.variables.set which creates local variables. As the life time of local variable is the entire collection run and after that it will be destroyed, so for every new collection run the value will be undefined.
we are setting the value to 3 if its undefined . and then sends the request till the value becomes less than 1.

JavaScript while loop + setInterval doesn't work in Django

I'm developing a website using Django. I have about 50 functions. And it takes about 1 minute to get the result for all of them.
The problem is that I use heroku for my app. And heroku has a limit of 30 sec to get the request. I was suggested to use background tasks. Now I am using background jobs in Python RQ. For each function I made a separate task in Views. Here is an example of one of the tasks:
task_robots_url = q.enqueue(Robots(url).get_url)
robots_url = task_robots_url.result
And now I need to check whether the job is finished in the Template. And when it's finished, display the result.
I want to check with JS each second whether the job is finished. If it's not finished - show "Loading ... " message to the user. If it's finished - show the result.
Here is my JS code:
<script>
var h1 = document.getElementById("h1");
var job_result = "{{ robots_url }}"
var test = function () {
if (job_result == "") {
h1.innerText = "Waiting...";
} else if (job_result == "None") {
h1.innerText = "Waiting ...";
} else if (job_result == undefined) {
h1.innerText = "Waiting ...";
} else {
clearInterval(inter);
h1.innerText = job_result;
}
}
var inter = setInterval(test, 1000);
</script>
But this doesn't work. When the result page starts - I've got an empty result. And it displays Waiting. Then I have None result. And it still displays Waiting. But now after waiting there is no result.
In the documentation for Python RQ it is said I should put time.sleep() for several seconds in my code. And if I put time.sleep(2) - I got the result. But if I put time.sleep(2) for each of my 50 functions - I will get 100 sec. And the limit in Heroku is only 30 sec... So I need to check and display the result without sleep()...
The setInterval() method calls a function or evaluates an expression at specified intervals (in milliseconds).
The setInterval() method will continue calling the function until clearInterval() is called, or the window is closed.
You are calling setInterval so many times which cause your browser to crash eventually.
assuming job_result value changes after 10 sec you can write the following code:
var job_result = {{ job_result }};
var loadingMessage = function (){
if (!job_result) {
document.write("Loading ...");
}
else {
return
}
}
setInterval(() => loadingMessage, 1000);
You can call return to stop the Interval for running or you can use setTimeout and to call a function that clears the interval

How to repeat iteration based on number of retries

I am uploading file chunks to Dropbox and I need to add a simple retry into my loop. So if the first attempt fails, retry another 2 times before giving up.
To give some context. Im uploading a file in chunks to Dropbox. But, I need to allow the script to fail gracefully. Asking the script to repeat the upload 3 times before I kill the upload and give the user an error.
For example (not actual attempt just a concept):
var retries = 3;
jQuery(dropbox.chunks).each(function(index, chunk){
var result = anothingFunction();
if (result == true) {
//continue the loop
}
if (result == false) {
retries--;
if (retries > 0) {
//Retry this iteration
}
if (retries = 0) {
//Kill the entire loop as this upload clearly is not going to happen.
}
}
}

Simplest possible irrevocable timout / cooldown function?

I'm trying to add a 1 second cooldown to my send-message system (as in, you can send 1 message per second max). So my initial thought was simply to create a timeout, and before attempting in sending to check if it exists still. That turned out to take more line of code than I anticipated initially.
Is there something I'm missing here? Isn't there something as simple as:
//inside some message sending function
if(!mySuperCooldown)
{
//send message
mySuperCooldown = cooldown(1000);
}
Everything else I construct successfully ends up taking loads of lines, and it appears to me as something someone thought of before. Thank you, and excuse my illiteracy.
Have a flag that allows messages, and set it to false when a message is sent. Then set a timeout for 1000 milliseconds that resets the flag to true.
var allowMessage = true;
function sendMessage(msg) {
if (allowMessage) {
//do something
allowMessage = false;
setTimeout(() => allowMessage = true, 1000);
}
}
Make a higher order function that turns a normal function into one that is rate limited:
function rate_limit(delay, func) {
var last_call = null;
return function() {
if (last_call && (Date.now() - last_call <= delay)) {
return;
}
last_call = Date.now();
return func();
};
}
You can then rate limit any function:
var my_function = rate_limit(1000, function() {
console.log('foo');
});
Running my_function() will only call your original function once per second.

Iterate array in Javascript with Sleep

Hi I am making one site in RubyOnRails. I am having problem in showing some content at client side. What I want to do is like news where after every 10 sec., news would change. What I have done is I have make an ajax which fetch the news from my server, server returns array in json response. Now I have all the news array at client side I want to show one by one in 10 sec interval.
I have tried with this code but its not showing anything except last news.
function get_news(){
$.ajax({
url : "my.json",
success:function(data){
// data is array of json like [{"html" : "dfsf"},{"html":"ddd"}]
news_change(data);
}
});
}
get_news();
function news_change(feed){
$.each(feed,function(index,f){
var feed_html = f.html;
$('#news_div').fadeOut('slow', function(){
$('#news_div').html(feed_html);
$('#news_div').fadeIn('slow');
});
sleep(10000);
});
}
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
when I execute this code it only shows news which is last. And also it hang my browser. Please suggest me why is this because ?
Use setTimeout or setInterval, which execute code asynchronously after a certain number of milliseconds. Looping is synchronous and locks the browser while it executes.
// this will execute get_news every 10,000 ms
var newsInterval = setInterval(get_news, 10000);
// if you ever want to stop the interval, use clearInterval
clearInterval(newsInterval);
Note that get_news performs an ajax call, which could take some time, meaning that your news will not update exactly every 10 seconds.
EDIT: to iterate through the news array every 10 seconds, you'd pass the news_change function to setInterval:
var newsInterval;
function get_news(){
$.ajax({
url : "my.json",
success:function(data) {
newsInterval = setInterval(function () {
news_change(data);
}, 10000);
}
});
}
get_news();
// if you ever want to stop the interval, use clearInterval
clearInterval(newsInterval);

Categories

Resources