How does Rx really work on web (client side) - javascript

I have gone through the introduction part at Rx CodePlex page. I have watched the video of the guy with CascadiaJS. I have discovered how the RxJS library is used. I have a question about how is it going to help me with my existing Ajax application and what do I have to change on server side as well as client-side to make the most of RxJS.
Scenario
I have a REST service written using ASP.NET Web API. The service currently has one method, it takes an array of coordinates and return another array of coordinates. So the call is very simple, it goes like this.
$.ajax({
url: "http://www.myservice.com/service1/",
type: "POST",
data: JSON.stringify(params),
contentType: "application/json;charset=utf-8",
success: handle_success,
error: handle_failure,
OPTIONS: null,
});
Now the above call simply calls a REST service and takes appropriate action on how the results come out.
With Rx, I heard the mantra of "Push" instead of Pull. How are we going to fit "Push" into the sample above ? Am I going to change my REST service to be a Listening TCP Socket which my webpage will stay connected (or make a Keep-Alive connection) and new values will be "Pushed". Or this would just be a service call as above, but the success/error will just be "channeled" through Observable and once the call is finished, the job of that Observable is finished ?

Even without worrying about changing your server to push to the client, RxJs can help you compose your asynchronous actions on the client.
For example, if you model your ajax call as an observable:
// each time you subscribe to service, it will execute the ajax call and send back the result
var service = Rx.Observable.defer(function () {
return $.ajax({
url: "http://www.myservice.com/service1/",
type: "POST",
data: JSON.stringify(params),
contentType: "application/json;charset=utf-8"
});
});
// Now fun with Rx
// just call the service like in your OP example:
service.subscribe(handle_success, handle_failure);
// poll the service every 5 seconds
var pollInterval = Rx.Observable.empty().delay(5000);
service
.concat(pollInterval)
.repeat()
.subscribe(success, failure);
// run the service whenever user clicks Refresh
$('#refresh')
.onAsObservable('click')
.flatMap(function () { return service; })
.subscribe(success, failure);
// same as above, but ignore it when user clicks too fast (e.g. faster than 1 second)
$("#refresh")
.onAsObservable('click')
.debounce(1000)
.flatMap(function () { return service; })
.subscribe(success, failure);

Related

If api server is down, what is the best practice to alerting users that the server is currently unavailable clientside?

I have a website that basically makes API calls and displays the data in a table; the API is on a different server from the website.
If the API server is down what is the best way to alert the user client-side (JavaScript) that the server is unavailable?
Could/Should I put the alert in the API call error handling (See code for example)? What is the best practice for this type of situation.
function apiCall(query, product){
var p = product;
var urlr='https://myFakeAPIUrl/api/'+query+'/'+ product;
$.ajax({
contentType: 'application/json',
crossDomain: true,
url: urlr,
type: "GET",
success: function (result){
alert("Yay, the API server is up.");
},
error: function(error){
console.log(error);
alert("Sorry, the server is down.");
}
});
}
var productData = apiCall("Produce", "112233");
I would ask myself what a user would like to see in this situation.
What I always do is putting a timeout on the Ajax request, whenever that timeout of e.g. 9999ms runs out, the user should get notified (with a toast, a heading, etc..) that something went wrong and that they should try it again later.

PHP Thread telling to JavaScript that will sleep

The title is a little confuse, but my problem is:
Javascript do an AJAX Request to the PHP Controller. In the PHP Controller a Thread is created and started. The code is:
public function run() {
while(true) {
//Do Something...
//Know I want to tell Javascript that I have done the thing and I'm going to sleep.
sleep(10000);
}
}
So the JavaScript code is:
$.ajax({
type: 'POST',
url: "controllers/DatabaseController/",
data: dataObject,
success: function(response) {
//Do Something after the Thread Result
}
});
I am thinking that this problem it's impossible... Because the Thread runs and sleep after a time set by the client. And when the Thread runs, the client side need to see the results of the Thread.
How can I do this? The Javascript need to be in a loop like the PHP Thread?
The situation is:
- Thread do polling of the equipments status and after that the javascript change the icons status (green or red) of the equipments.
What you can do is:
Create two controller methods: One to start the thread the other one to check the status of it.
You make your ajax request to start the thread. Once the thread is started, you return a response, with a success/error message.
If the thread was started successfully, you will then make a second ajax request periodically to check the status of the thread.
You may also, in the first call, return the expected time the thread will sleep so you can adjust the time which the second ajax request will be made.
Edit (trying to clarify):
Let's say that your thread will check how much fuel the machine has. That thread will query the machine and will save that into a database.
The second method in the controller will query the database and fetch the results saved by the thread.
Example:
Controller:
class Controller
{
public function startThread()
{
// start thread
// return
}
public function checkStatus()
{
// query database for status
// return results
}
public function thread()
{
// check for machines status
// save the results into database
}
}
Javascript:
$.ajax({
type: 'POST',
url: "controller/startThread/",
data: dataObject,
success: function(response) {
// if success
setTimeout(function() {
$.ajax({
type: 'POST',
url: "controller/checkStatus/",
data: dataObject,
success: function(response) {
// your result will be here
})
}, 10000)
}
});
Solution:
I used the javascript function setInterval with the time that user set, who runs a function that do an ajax request to the php controller.
The Controller create a thread that do the polling of the equipments and die.

jQuery is not calling .done() when the ajax call is successful

We're building a node.js application using Express, but are separating our layers. So the browser is running pure jQuery and javascript, the web server and application server are Node.js and Express. We're using REST APIs between them all.
We're using jQuery 1.10.2
Since the application server cannot be open to the public, the browser must make API calls to the web server, which manages making the call to the application server and returning the results. Here is what that looks like...
// Proxy all other API calls to the backend server
var request = require('request');
app.all('/api/*', function (req, res) {
var targeturl = apihost+req.originalUrl;
console.log("Proxy: "+targeturl);
request({
url: targeturl,
method: req.method,
json: req.body
}, function (error, response, data) {
if(error) {
res.send(error);
res.end();
} else {
console.log("SUCCESS...");
console.log(data);
res.send(data);
res.end();
}
});
});
Our data is a two-level hierarchy of Flows and one or more child Milestones on each Flow. When someone clicks the Save link on our page to save a Flow and its Milestones, the Javascript pulls the Flow data from the page, then makes an AJAX call to save the Flow information first, then waits for the "done()" handler before pulling the Milestone information from the page and making a second AJAX call to save that data. Here is the saveFlow() function executed in the browser...
function saveFlow(organization_id, user_id, flow_id) {
var name = $('#Name').val();
var purpose = $('#Purpose').val();
console.log("Trying to save flow: " + flow_id);
if (name && name.length > 0) {
$.ajax({
url: "/api/flow",
type: 'POST',
datatype: 'json',
data: {
flow_id: flow_id,
name: name,
purpose: purpose,
organization_id: organization_id,
user_id: user_id,
timestamp: (new Date())
}
})
.fail(function (error) {
console.log("Could not save the flow: " + error.message);
})
.done(function (flow) {
console.log("Saving milestones for flow "+flow.id+" ["+flow_id+"]");
saveMilestones(flow.id);
});
} else {
console.log("Refusing to save a flow that has no name");
}
}
The proxy code shows me that this call succeeded...
SUCCESS...
{ success: true,
message: 'Flow Updated!',
id: '56de8e346d229b492a0954f9' }
But the proxy code also demonstrates that the next API call never takes place. Moreover, the log statement in the Done block is never executed, nor are any log statements placed inside the saveMilestones() function.
Clearly, the .done() handler is never being called in this case. I use the done() handler in other parts of my code and it works. I've compared the code but don't see any differences. The proxy code we're using is driving every other API call made from our pages successfully, so I don't think that it's failing to return the success status.
I've done a lot of searching on this site and tried every suggestion I could find - adding a explicit "json" datatype parameter, switching from ":success" to ".done()" - but nothing has worked yet. I even tried switching from done() to always() - a bad idea but I wanted to see if it would get called...and it wasn't called.
It's also worth noting that the .fail() handler is also not being executed.
Is it possible that the JSON block we're sending back to indicate success is somehow failing to make jQuery realize that we were successful? Or is it possible that the AJAX call is crashing when it tries to process the successful return? If so, how do I catch that to prove it and fix it?
Hope someone can help.

Feeding webpage data via remote Web API

I'm trying to operate two servers.
MVC Web API service.
MVC Web application.
The idea is that the web application renders a page filled with javascript requests, which populate the actual data from the remote API service. The web application will never itself touch the database, or the API service (besides setting up authorisation tokens initially).
What is the best way to achieve this?
So far I've been using JQuery AJAX requests, attempting to use JSONP. However I always get "x was not called" exceptions.
$.ajax({
url: '#(ViewBag.API)api/customer',
type: 'get',
dataType: 'jsonp',
jsonp: false,
jsonpCallback: function (data) {
debugger;
// code to load to ko
},
error: function (xhr, status, error) {
alert(error.message);
}
});
Also the jsonpCallback function is called before the request is sent, so I assume its actually trying to call a function to generate a string? If I reform this request:
window.success = function (data) {
debugger;
// code to load to ko
};
... with jsonpCallback being "success", I still get the same error (but the success method is never called.
Any ideas? Thanks.
Edit: I've gotten started on the right course from this:
http://www.codeproject.com/Tips/631685/JSONP-in-ASP-NET-Web-API-Quick-Get-Started
Added the formatter, and replaced jsonCallback with success, like a normal ajax. However this only seems to work for get. I cannot delete or update. :(
Can you get it to work using the $.getJSON method?
$.getJSON( "ajax/test.json", function( data ) {
//handle response
});
Have you fired up developer tools in IE and watched the network traffic to see precisely what is being sent and returned?

javascript: handling client side initiated objects that the server hasn't assigned an id to

I'm developing a javascript application and I'm trying to make server side syncing as automagic and unobtrusive as possible
The problem I'm facing is that when creating an object client side I can immediately send the create ajax request and while I'm waiting for it to return add the object to the ui where necessary
However since the object has no id until the server responds I can't perform any update or destroy actions on it until the server responds and updates its id
What is the best way of dealing with this problem?
Some code if it helps:
create_object = function() {
return {
save: function() {
if (this.isNew()) {
this.create();
} else {
this.update();
}
},
isNew: function() {
return (this.id === undefined || this.id === null);
},
update: function () {
$.ajax({
url: '/update_object/'+this.id+'.json',
type: 'post',
dataType: 'json',
data: this
});
},
create: function () {
var object = this;
$.ajax({
url: '/create_object',
type: 'post',
dataType: 'json',
data: this,
success: function(data) {
object.id = data.id;
}
});
},
destory: function () {
$.ajax({
url: '/destroy_object/'+this.id+'.json',
type: 'get',
dataType: 'json'
});
}
};
};
var object = create_object();
object.message = "Foo!";
object.save();
// this will create a new object until object.save has responded
object.message = "Bar!";
object.save();
// this wont work until object.save has responded
object.destroy();
This is not really a problem. AJAX is asynchronous by nature (Asynchronous Javascript and XML). You will have to wait until you get a response from the server to update your UI.
If you must update the UI immediately, you can create an element with a placeholder ID that you can then update with the actual ID once the server responds.
UPDATE
This is in response to your comment. Webapps are not purely client-side applications. They fit into the client-server paradigm. You can try using a synchronous post, but this has the side-effect of tying up the browser until the server responds (this is due to the fact that Javascript is single-threaded).
That being said, the response from the server should be pretty quick unless your network is slow or if whatever post your sending to the server results in some computationally-intensive operation.
Going by the placeholder route will (as you have realized) result in all sorts of new problems that you have to deal with. You have to ensure that they are unique. Now what if they perform some operation on the client-side element before the server responds with an id? The server won't know what the placeholder id means. There are ways around this (queuing requests is one way), but it will make your code a whole lot more complicated. I don't think the tradeoff is worth it just to make the UI update faster.
An option is to provide some visual feedback to the user that the app is "working" (i.e., while you are waiting for a response from the server). A spinner, for example.
As far as stacking the AJAX requests, that is one approach that you can take using the jQuery message-queuing plugin.

Categories

Resources