Non-blocking function calls with Boost - javascript

I have this function that is called from Javascript (Browser):
STDMETHODIMP CActivexObject::WriteToREST(BSTR data, BSTR* retstr)
{
std::string sdata = ConvertToString(data);
RESTClient restclient;
RESTClient::response resp = restclient.post("somewhere.com", "/post", sdata);
CComBSTR bstrResult(resp.body.c_str());
*retstr = bstrResult.Detach();
return S_OK;
}
This method is called from the Javascript like this:
for (var i = 0; i < rowElems.length; i++) {
var resp = ActivexObject.WriteToREST(_rowToData(rowElems[i]));
}
The function works fine, unless the call to REST or the server gets slow, and the Javascript (Browser), i.e. Internet Explorer to show "Not Responding" error box. Then browser shuts down. If I remove the "post" call and just log the data, the there's no such error like this.
Sometimes the WriteToREST is called twice or three times.
What could be a possible solution for this that I can make with the C++ code?

Related

XMLHttprequest.send(null) is crashing my code

I'm currently writing a search function using JavaScript.
However, when I attempt to test my creation, I find that it stops about halfway through for no discernible reason.
Below is my code:
document.getElementById("test").innerHTML = "";
var Connect = new XMLHttpRequest();
Connect.open("GET", "xmlTest.xml", false);
document.getElementById("test").innerHTML = "1";
Connect.send(null);
document.getElementById("test").innerHTML = "2";
var docX = Connect.responseXML;
var linjer = docX.getElementsByTagName("linjer");
The first line is there to clear a potential error message from earlier in the code. Then I attempt to open up an XML file, as I need to read from it.
As you can see, I've entered two debug statements there; they will print 1 or 2 depending on how far I get in the code.
Using this, I've found that it stops exactly on the Connect.send(null); statement (as 1 gets printed, but 2 never does), but I can't figure out why. Google says that it might be that chrome can't access local files, but when I found a way to allow Chrome to do this, it still did not work.
What am I doing wrong?
This might be a synchronous issue that requires a response that your code simply is not getting.
Try using an async call instead:
Connect.open("GET", "xmlTest.xml", true);
Also make sure to setup proper callbacks since you'll be using async here now instead of synchronous code, like so:
// Global variable scope
var docX;
var linjer;
// Define your get function
getDoc = function(url, cbFunc) {
var Connect = new XMLHttpRequest();
// Perform actions after request is sent
// You'll insert your callback here
Connect.onreadystatechange = function() {
// 4 means request finished and response is ready
if ( Connect.readyState == 4 ) {
// Here is where you do the callback
cbFunc(Connect.responseXML);
}
};
// 'true' param means async, it is also the default
Connect.open('GET', url, true);
Connect.send();
}
// Define your callback function
callbackFunction = function(responseXML) {
// XML file can now be stored in the global variable
window.docX = responseXML;
window.linjer = window.docX.getElementsByTagName("linjer");
}
// And here is the call you make to do this
getDoc("xmlTest.xml", callbackFunction);
For better understanding of all of this, do some research on scope, closures, callbacks, and async.

Recursive calls to a server using AJAX not working in Internet Explorer

I am developing a web-application on File Management System in which I have to access various directories on my system and list them on my web page. I have used AJAX to make rest calls to the server. I have created a rest-controller to handle the requests.
I am encountering a problem in the execution of a java-script function which I have to call recursively on the basis of a counter. The function is to navigate backwards in a directory. If the value of count is zero, I will display the result on the web page, else I will recursively call the function. The function works as expected in Chrome but not in IE-11.
I want to make multiple calls to the server based on the counter value. Hence I am calling the function recursively, but the call to the server is made only once. This problem occurs in IE-11. In Chrome, it works perfectly.
The function is:
function gobackDir(count) {
var back_count = count;
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET","http://neha:8080/myServer/goback",true);
xmlhttp.send();
xmlhttp.onreadystatechange=function($event) {
if ($event.currentTarget.readyState==4 && $event.currentTarget.status==200) {
back_count--;
if (back_count > 0) {
gobackDir(back_count);
}
else {
var server_response = JSON.parse($event.currentTarget.response);
set_currentDirectory(server_response);
set_directoryContent(server_response);
}
}
}
}
In IE, you need to bust the cache:
var bustCache = (new Date()).getTime();
xmlhttp.open("GET","http://neha:8080/myServer/goback?" + bustCache,true);

WebSocket sends message only after the loop get completed

I have a code like below:
var ws = new WebSocket("ws://localhost");
ws.onopen = function() {
// Long running loop
for (var i = 0; i < 1000000; i++) {
ws.send(i);
console.log(i);
}
};
The server only receives message (or I believe the client only starts sending message) after the loop gets completed. Why is this so?
Some areas of execution with a page are:
JavaScript
DOM rendering
Network
I've not tested this for a while, but I'm assuming it is still the case, that if you execute a function (or run code in one scope) then if you make a call to update the DOM or make a network request that won't happen until the current scope exists.
e.g.
function doSomething() {
document.body.innerHTML += 'hello';
var ws = new WebSocket('ws://my-websocket-endpoint.com');
ws.onopen = function() { alert( 'awesome!' ); };
}
doSomething();
In the code above the following will happen:
doSomething executes and the internal code is run.
doSomething returns and the scope changes
'hello' then appears in the DOM as the browser gives the UI thread a chance to run any pending updates
The WebSocket connection is made
It may be a while until the alert fires.
Looking specifically at the WebSocket example. If you think about the fact we can add event handlers after we create the WebSocket instance this means that the connection doesn't occur as soon as we call the constructor. The connection is only attempted when the current scope of executions completes. I can't 100% confirm this, but it's also highly unlikely that the WebSocket.send function actually sends any data until the scope of execution completes e.g.
var ws = new WebSocket('ws://my-websocket-endpoint.com');
function sendStuff() {
for( var i = 0; i < 10000; ++i ) {
ws.send( i );
}
}
// Assume we are connected
sendStuff();
In the above code I would expect:
sendStuff to be called, run the loop and exit
The browser to then deal with anything else that's pending, including network activity. This includes actually sending the data
It doesn't answer your question but its worth noting that your code looks incorrect.
Your new WebSocket call initiates an asynchronous handshake with the server. When this completes, any onopen callback you registered on your websocket will run. It is only at this time you can call ws.send and expect the server to receive your message.
You could then rework your example to
var ws = new WebSocket("ws://localhost");
ws.onopen = function() {
for (var i = 0; i < 1000000; i++) {
ws.send(i);
console.log(i);
}
};

web workers behave differently in webkit than Firefox

I have a web application that works just fine in modern webkit-based browsers (http://montecarlo-tester.appspot.com/). Basically it uses a webworker to fetch data from a server, and then sends it back after performing some computations.
It works just fine in Chrome/Safari (no errors in console), but when I try to use it in Firefox, it doesn't. I've deduced that somehow the variable 'iterations' is not set properly in Firefox. Unfortunately, Firefox lacks a debugger (for web workers), and javascript has functional scoping, so it's really hard to pinpoint where the problem is. I've posted the javascript code for my web worker, and I was wondering if anybody could point out where I went wrong:
importScripts('/static/js/mylibs/jquery.hive.pollen-mod.js');
$(function (data) {
main();
//while(main());
close();
});
function main() {
//make an ajax call to get a param
var iterations//value will be set by server response
var key//key of the datastore object
var continueloop = true;
p.ajax.post({
url:'/getdataurl',
dataType: "json",
success: function(responseText){
if (responseText === null) {
var workermessage = {
"log":"responseText is null. Either the server has issues or we have run out of stuff to compute."
};
$.send(workermessage);
continueloop = false;
}
iterations = responseText.iterationsjob;
key = responseText.key;
}
});
if (continueloop === false) {
return false;
}
//here is where I think the problems begin. In chrome/safari, iterations = 1000.
//In Firefox however, iterations = null. As a result, everything after that does not work.
var i,x,y,z;
var count = 0;
var pi;
start = new Date();
for (i=0;i<iterations;i++) {
x = Math.random();
y = Math.random();
z = x*x+y*y;
if(z<=1.0){
count++;
}
}//end for loop
pi = count/(iterations)*4.0;
end = new Date();
result = {
"estimated_pi":pi,
"num_iter":iterations,
"duration_ms":end.valueOf()-start.valueOf(),
"key":key
};
//send results to the server
p.ajax.post({
url: "/resultshandler",
dataType:'json',
data: result,
success: function()
{
//do nothing!
}
});
$.send(result);
return true;//persists the loop
}
You're doing an async XHR, then immediately doing a loop trying to use its results. I have no idea why this possibly works in Chrome, but it's definitely racy. Have you tried passing "sync:true" in your post options?
Edit: Oh, nevermind. I see why your code works. The hive.pollen script has this wonderful bit:
sync: navigator.userAgent.toLowerCase().indexOf('safari/') != -1 ? false : true,
So it's doing a sync XHR in Chrome/Safari and an async one in everything else, by default (because it passes options.sync as the value for the async argument to XMLHttpRequest.open, which is backwards, but whatever; it does mean that you actually need to pass sync: false at the callsite to get sync behavior). And since you don't specify whether you want sync or async, you get sync in Chrome and async in Firefox.
Oh, and the script has this wonderful comment before that line:
// TODO: FIX THIS.

How to implement a getter-function (using callbacks)

I have to request data for a JS-script from a MySQL database (based upon a user-id).
I did not find a simple solution for JavaScript and it was not possible to load the data using ajax, because the database is available under a different domain.
I implemented a workaround using PHP and curl.
Now the JS has to "wait" for the request to finish, but the script is of course running asynchronously and does not wait for the response.
I know that it's not really possible to wait in JS, but it must be possible to return value like this.
I also tried using a return as another callback, but that didn't work of course, because the getter-function will run further anyway.
How can I implement a simple getter, which "waits" and returns the response from the HTTP-request?
Thanks for any other clues. I'm really lost at the moment.
This is a excerpt from the source code:
/**
* Simple getter which requests external data
*/
function simple_getter() {
// http request using a php script, because ajax won't work crossdomain
// this request takes some time. function finished before request is done.
/* Example */
var url = "http://example-url.com/get_data.php?uid=1234";
var response_callback = handle_result_response;
var value = send_request( url, response_callback );
value = value.split('*')[0];
if (value === '' || value == const_pref_none) {
return false;
}
/* 1. returns undefinied, because value is not yet set.
2. this as a callback makes no sense, because this function
will run asynchronous anyway. */
return value;
}
Additional information about the used functions:
/**
* Callback for the send_request function.
* basically returns only the responseText (string)
*/
function handle_result_response(req) {
// do something more, but basically:
return req.responseText;
}
/**
* Requests data from a database (different domain) via a PHP script
*/
function send_request( url, response_callback ) {
var req = createXMLHTTPObject();
if (!req)
return;
var method = (postData) ? "POST" : "GET";
req.open(method, url, true);
req.setRequestHeader('User-Agent','XMLHTTP/1.0');
// More not relevant source code
// ...
req.onreadystatechange = function () {
// More not relevant source code
// ...
response_callback(req);
}
if (req.readyState == 4)
return;
req.send(postData);
}
Not really relevant code, but required for the HTTP-request:
var XMLHttpFactories = [
function () {return new XMLHttpRequest()},
function () {return new ActiveXObject("Msxml2.XMLHTTP")},
function () {return new ActiveXObject("Msxml3.XMLHTTP")},
function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];
function createXMLHTTPObject() {
var xmlhttp = false;
for (var i=0; i<XMLHttpFactories.length; i++) {
try {
xmlhttp = XMLHttpFactories[i]();
} catch (e) {
continue;
}
break;
}
return xmlhttp;
}
You really, really shouldn't try to synchronously wait for a network request to complete. The request may never complete, may hang and take a long time, and so on. Since JavaScript is single threaded, and in fact all major browser engines are single threaded, this will cause your entire page to hang while waiting for the request, and in some browsers, may cause the entire browser to hang.
What you should do is replace code like this:
var returned = some_request('http://example.com/query');
do_something_with(returned);
with code like this:
some_request('http://example.com/query', function (returned) {
do_something_with(returned);
});
That way, you will never cause your page or the browser to hang waiting for the request, and can simply do the work once the response comes in.
I don't see whats wrong with your code in general.
When you make a request, provide a Callback. When a response comes back, which you can easily detect, execute the Callback and pass it the result.
This is the way client side apps work.It is not procedural, but works by events.
You present the screen to the user and wait
The user makes an action
You call the server, set a callback and wait
The response come and you execute the callback and wait for another step 2
Rather than trying to change that, you need to fit with that or it will be a painful experience.
Javascript is not multithreaded. It means a single statement is run at a time. The real asynchronism come from the time the server takes to respond and call the callback. You never know which call will come first and need to build your program with that in mind.

Categories

Resources