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);
Related
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
I'm writing a Tampermonkey script for a web page and trying to extract data from other pages.
I'm trying to make a function that has a loop inside that goes thru a list, llcList, and retrieves data from ajax method GET, but would like to wait for to finish one request before going to second one.
Bonus would be if I could make it wait some extra time.
What should happen:
send request for a llcList[0]
get return data, process it
wait some time
send new request for a llcList[1]
Is this possible? I tried few methods, every time loop send all requests not a second apart. :
function F_Company_LLC(){
for (i = 0; i < llcList.length;i++) {
if(llcList[i][2]=="lab"){
//run function 0
//break;
}
else if(llcList[i][2]=="shop"){
//run function 1
//break;
}
else{
F_GET_CompData(llcList, llcList[i][1],i,function(result){
console.log(result);
});
}
}}
function F_GET_CompData(F_GET_CompData_list, CompID, F_GET_CompData_row, callback){
$.ajax({
method : "GET",
url: base_link+"/company/edit_company/"+CompID,
beforeSend: function(){runningRequest++;},
success: function(data){
//data processing
runningRequest--;
},
error: function() {console.log("Get_ComData");}
});
callback(runningRequest);}
This is a common scenario. Note that it's often unnecessary to process the calls sequentially though. It's usually adequate to just send context with the ajax calls and piece everything together as it comes in semi randomly, as shown in this answer.
One way to force sequential behavior is to chain calls via the complete function. Here is fully functional code that demonstrates the process. To use, paste it into your browser console while on a Stack Overflow page. :
var listO_pages = ["q/48/", "q/27/", "q/34/", "q/69/", "badpage"];
var numPages = listO_pages.length;
getPageN (0); //-- Kick off chained fetches
function getPageN (K) {
if (K >= 0 && K < numPages) {
let targPage = listO_pages[K];
$.ajax ( {
url: "https://stackoverflow.com/" + targPage,
context: {arryIdx: K}, // Object Helps handle K==0, and other things
success: processPage,
complete: finishUpRequest,
error: logError
} );
}
}
function processPage (sData, sStatus, jqXHR) {
//-- Use DOMParser so that images and scripts don't get loaded (like jQuery methods would).
var parser = new DOMParser ();
var doc = parser.parseFromString (sData, "text/html");
var payloadTable = doc.querySelector ("title");
var pageTitle = "Not found!";
if (payloadTable) {
pageTitle = payloadTable.textContent.trim ();
}
var [tIdx, tPage] = getIdxAndPage (this); // Set by `context` property
console.log (`Processed index ${tIdx} (${tPage}). Its title was: "${pageTitle}"`);
}
function finishUpRequest (jqXHR, txtStatus) {
var nextIdx = this.arryIdx + 1;
if (nextIdx < numPages) {
var tPage = listO_pages[nextIdx];
//-- The setTimeout is seldom needed, but added here per OP's request.
setTimeout ( function () {
console.log (`Fetching index ${nextIdx} (${tPage})...`);
getPageN (nextIdx);
}, 222);
}
}
function logError (jqXHR, txtStatus, txtError) {
var [tIdx, tPage] = getIdxAndPage (this); // Set by `context` property
console.error (`Oopsie at index ${tIdx} (${tPage})!`, txtStatus, txtError, jqXHR);
}
function getIdxAndPage (contextThis) {
return [contextThis.arryIdx, listO_pages[contextThis.arryIdx] ];
}
This typically outputs:
Processed index 0 (q/48/). Its title was: "Multiple submit buttons in an HTML form - Stack Overflow"
Fetching index 1 (q/27/)...
Processed index 1 (q/27/). Its title was: "datetime - Calculate relative time in C# - Stack Overflow"
Fetching index 2 (q/34/)...
Processed index 2 (q/34/). Its title was: "flex - Unloading a ByteArray in Actionscript 3 - Stack Overflow"
Fetching index 3 (q/69/)...
Processed index 3 (q/69/). Its title was: ".net - How do I calculate someone's age in C#? - Stack Overflow"
Fetching index 4 (badpage)...
GET https://stackoverflow.com/badpage?_=1512087299126 404 ()
Oopsie at index 4 (badpage)! error Object {...
-- depending on your Stack Overflow reputation.
Important: Do not attempt to use async: false techniques. These will just: lock up your browser, occasionally crash your computer, and make debug and partial results much harder.
To explain the question. I have a dojo toolkit code which polls an open-monica server every 1 second to display the value on screen. I am trying to make an alarm which checks the values every 40 and 60 seconds. Therefore I am wondering if there is a function which can run alongside the passive polling of the dojo toolkit. I have tried setInterval() and setTimeout() however both of those stops the polling of the monica server
My code is:
require(["dojo/dom-attr", "atnf/monica", "dojo/domReady!"], function(domAttr, monica) {
function valCheck(){
}
// The callback is called separately for each point
// that has new data, so we only need to accept the reference to that
// point as an argument.
var pageUpdate = function(pointReference) {
var values = pointReference.latestValue(); //obtain the updated values
domAttr.set("htmlPageDiv", "innerHTML", values.value); //display the moniva value in their corresponding div in the html page
}
};
// We set up the connection to the MoniCA server.
var monicaServer = monica.server({
'webserverName': "some server",
'serverName': "serverName",
"webserverPath": "webServerPath",
'updateInterval': 1000, // in ms
'autoDescriptions': true
});
// Connect to it now, and when that is done, tell it which
// points we want to query.
monicaServer.connect().then(function(serverObj) {
//add monica points to check in the server
var points = monicaServer.addPoints(["some data point", "another data point", "etc."]);
// Tell the server connector which function to call on each
// update, for each point (we use the same callback for each.
for (var i = 0; i < points.length; i++) {
points[i].addCallback(pageUpdate);
}
// Get the descriptions and then start updating.
monicaServer.getDescriptions();
monicaServer.startUpdating();
});
});
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 7 years ago.
So I'm trying to build a web application that will ping a device's registers for stored data every 30 seconds.
as you can see each device can have multiple registers. When a user creates a new device I iterate all the newly created register id's that I return from my ajax post(generated DB id's) and then start an interval timer making an ajax call every 30 seconds to a method that will ping my device and get the data for the specific register.
The problem I'm running into is that every time the interval runs my ajax call, it's reusing the last register id to fetch data instead of running a fetch on each individual register. Ex. my 2 rows have an id of 22 and 23. Everytime my interval function is called it will use id 23 and make the ajax call instead of calling 22 then 23. Is this because I'm using a for loop when instantiating a new interval?
Here is how I try to handle my setInterval:
var registers = result.register_ids;
for (var i = 0; i < registers.length; ++i) {
debugger;
var interval = setInterval(function () { fetchRegisterValues(registers[i], result.modbus_id) }, 30000);
register_ping_threads[registers[i]] = interval;
}
Here is my ajax call to read the specified register:
function fetchRegisterValues(register_id, modbus_id) {//id always ends up being 23
debugger;
$.ajax({
type: "POST",
url: "/fetch_mdata",
data: {
'csrfmiddlewaretoken': token,
'register_id': register_id, //use to read the register range
'modbus_id': modbus_id //used to get device connectiong settings
},
contentType: "application/x-www-form-urlencoded",
dataType: 'json',
success: function (result) {
debugger;
$('[data-register="' + register_id + '"]').find('[data-value=""]').text(result.value);
},
error: function (data) {
debugger;
$('#loading-icon').hide()
$('#ping_error').addClass('alert alert-danger');
$('#ping_error strong').append('Problem contacting server..');
}
});
}
This is a very common mistake in JavaScript. Remember that i is in a scope of a function, not the scope of the loop, so all your fetchRegisterValues will reuse the same value of i. To fix it, create a new scope:
for (var i = 0; i < registers.length; ++i) {
debugger;
var interval = setInterval((function (i) { return function() { fetchRegisterValues(registers[i], result.modbus_id) } })(i), 30000);
register_ping_threads[registers[i]] = interval;
}
I have a small program, when you click on an "entry", the editing mode is opened, and the entry is to edit locked for others. There is every 10 seconds sends an ajax request to update the timestamp in the table.
$(".entry-edit").click(function() {
// code
loopLockingVar = setInterval(function() { loopLockingFunction(id) }, 10000);
// code
});
Then I have a cancel button to updating the timestamp in the table to 0 and to clear the interval.
$(".entry-cancel").click(function() {
// code
clearInterval(loopLockingVar);
// code
});
It all works when editing only one entry, but if two or more processed simultaneously, and then click cancel, the interval for the first entry still further...
I have this tried:
var loopLockingVar;
$(".entry-edit").click(function() {
// code
if( ! loopLockingVar) {
loopLockingVar = setInterval(function() { loopLockingFunction(id) }, 10000);
}
// code
});
However, this does not work more if you cancel and again clicks on edit...
You're assigning multiple interval IDs to the same variable which will only hold the interval ID that was assigned to it last. When you clear the interval, only the interval corresponding to that ID will be cleared.
A straightforward solution would be to maintain an array of interval IDs, and then clear all intervals represented in the array. The code could look something like this:
var intervalIds = [];
$(".entry-edit").click(function() {
intervalIds.push(setInterval(function() { loopLockingFunction(id) }, 10000));
});
$(".entry-cancel").click(function() {
for (var i=0; i < intervalIds.length; i++) {
clearInterval(intervalIds[i]);
}
});
maybe you can try like this.
var loopLockingVar;
$(".entry-edit").click(loopLockingVar,function() {
// code
loopLockingVar = setInterval(function() { loopLockingFunction(id) }, 10000);
// code
});