Is RTCDataChannel send() a synchronous/blocking call? - javascript

I'm trying to send a file in chunks over WebRTC, and I'm wondering if I can create a callback function to be called after RTCDataChannel.send() finishes sending each chunk of the file.
Is RTCDataChannel.send() a synchronous/blocking call? If so, my callback can be executed on the line after .send().
If .send() is asynchronous/non-blocking, then this will get tricky since it doesn't seem like .send() accepts a callback function, and I want to avoid using a buffer and a timeout.

The send method is blocking. It however doesn't wait until the data went over the wire, but only puts the data on an internal buffer from where it might later (or in parallel to the script execution) be sent.
The amount of data that has not been transmitted is available as the bufferedAmount property, which will be synchronously increased by every send() call (and not be updated otherwise until the next event loop turn).
You might make your wrapper asynchronous therefore, and put a timeout before actually calling send() when the currently buffered data is "too much" (by whatever criterion you see fit).

As noted above send() is effectively async - you don't get delivery receipt.
However there is a callback onbufferedamountlow which is invoked when
the channel drains it's send buffer below a value set with bufferedAmountLowThreshold
(see MDN onbufferedamountlow)
You can use that callback to decide when to send the next chunk.
Note however that this is relatively new to the draft standard and may not be supported everywhere.

Related

Firebase: Using an asyncronous call as part of a HTTP trigger without timing out?

I am currently learning firebase and I am trying to trigger an asynchronous Api call as part of a http trigger.
In the docs it says:
Resolve functions that perform asynchronous processing by returning a JavaScript promise.
Terminate HTTP functions with res.redirect(), res.send(), or res.end().
Terminate a synchronous function with a return; statement.
So what method could I use to make the network call without falling foul of the 60s limit - can I extend this?
Currently just calling to the network will occasionally time out as it goes over the 60s limit.
If your HTTPS trigger is always timing out, that means you aren't fully following the advice of the documentation you cited and always returning a response to the client.
If your HTTPS trigger simply takes over a minute to complete, and you need more time, you can increase the timeout in the Cloud console.

Does JavaScript WebSocket.send method block?

If I'm sending a large Blob or ArrayBuffer over a JavaScript WebSocket via its send method... does the send method call block until the data is sent, or does it make a copy of the data to send asynchronously so the call can return immediately?
A related (unanswered) question is, from how I interpret it, whether a rapid series of sends will cause onmessage events to be delayed, as someone seems to have described happening in Mobile Safari: Apparent blocking behaviour in JavaScript websocket on mobile Safari
Based on the description of the bufferedAmount attribute, I have deduced that send must return immediately, because otherwise bufferedAmount would always be zero. If it is non-zero, then there must be data buffered from a prior call to send, and if send buffers data, there's no reason for it to block.
From http://dev.w3.org/html5/websockets/
The bufferedAmount attribute must return the number of bytes of
application data (UTF-8 text and binary data) that have been queued
using send() but that, as of the last time the event loop started
executing a task, had not yet been transmitted to the network. (This
thus includes any text sent during the execution of the current task,
regardless of whether the user agent is able to transmit text
asynchronously with script execution.) This does not include framing
overhead incurred by the protocol, or buffering done by the operating
system or network hardware. If the connection is closed, this
attribute's value will only increase with each call to the send()
method (the number does not reset to zero once the connection closes).
In this simple example, the bufferedAmount attribute is used to ensure
that updates are sent either at the rate of one update every 50ms, if
the network can handle that rate, or at whatever rate the network can
handle, if that is too fast.
var socket = new WebSocket('ws://game.example.com:12010/updates');
socket.onopen = function () {
setInterval(function() {
if (socket.bufferedAmount == 0)
socket.send(getUpdateData());
}, 50);
};
The bufferedAmount attribute can also be used to saturate the network
without sending the data at a higher rate than the network can handle,
though this requires more careful monitoring of the value of the attribute over time.

Delaying a setTimeout()

I'm having an issue with some asynchronous JavaScript code that fetches values from a database using ajax.
Essentially, what I'd like to do is refresh a page once a list has been populated. For that purpose, I tried inserting the following code into the function that populates the list:
var timer1;
timer1 = setTimeout([refresh function], 1000);
As you might imagine, this works fine when the list population takes less than 1 second, but causes issues when it takes longer. So I had the idea of inserting this code into the function called on the success of each ajax call:
clearTimeout(timer1);
timer1 = setTimeout([refresh function], 1000);
So in theory, every time a list element is fetched the timer should reset, meaning that the refresh function should only ever be called 1 second after the final list element is successfully retrieved. However, in execution all that happens is that timer1 is reset once, the first time the second block of code is reached.
Can anybody see what the problem might be? Or if there's a better way of doing this? Thanks.
==========
EDIT: To clear up how my ajax calls work: one of the issues with the code's structure is that the ajax calls are actually nested; the callback method of the original ajax call is itself another ajax call, whose callback method contains a database transaction (incorrect - see below). In addition, I have two such methods running simultaneously. What I need is a way to ensure that ALL calls at all levels have completed before refreshing the page. This is why I thought that giving both methods one timer, and resetting it every time one of the callback methods was called, would keep pushing its execution back until all threads were complete.
Quite honestly, the code is very involved-- around 140 lines including auxiliary methods-- and I don't think that posting it here is feasible. Sorry-- if no one can help without code, then perhaps I'll bite the bullet and try copying it here in a format that makes some kind of sense.
==========
EDIT2: Here's a general workflow of what the methods are trying to do. The function is a 'synchronisation' function, one that both sends data to and retrieves data from the server.
I. Function is called which retrieves items from the local database
i. Every time an item is fetched, it is sent to the server (ajax)
a. When the ajax calls back, the item is updated locally to reflect
its success/failure
II. A (separate) list of items is retrieved from the local database
i. Every time an item is fetched, an item matching that item's ID is fetched from the server (ajax)
a. On successful fetch from server, the items are compared
b. If the server-side item is more recent, the local item is updated
So the places I inserted the second code block above are in the 'i.' sections of each method, in other words, where the ajax should be calling back (repeatedly). I realize that I was in error in my comments above; there is actually never a nested ajax call, but rather a database transaction inside an ajax call inside a database transaction.
You're doing pretty well so far. The trick you want to use is to chain your events together, something like this:
function refresh()
{
invokeMyAjaxCall(param1, param2, param3, onSuccessCallback, onFailureCallback);
}
function onSuccessCallback()
{
// Update my objects here
// Once all the objects have been updated, trigger another ajax call
setTimeout(refresh, 1000);
}
function onFailureCallback()
{
// Notify the user that something failed
// Once you've dealt with the failures, trigger another call in 1 sec
setTimeout(refresh, 1000);
}
Now, the difficulty with this is: what happens if a call fails? Ideally, it sounds like you want to ensure that you are continually updating information from the server, and even if a temporary failure occurs you want to keep going.
I've assumed here that your AJAX library permits you to do a failure callback. However, I've seen some cases when libraries hang without either failing or succeeding. If necessary, you may need to use a separate set of logic to determine if the connection with the server has been interrupted and restart your callback sequence.
EDIT: I suspect that the problem you've got is a result of queueing the next call before the first call is done. Basically, you're setting up a race condition: can the first call finish before the next call is triggered? It may work most times, or it may work once, or it may work nearly all the time; but unless the setTimeout() is the very last statement in your "response-processing" code, this kind of race condition will always be a potential problem.

Why is AJAX called asynchronous?

Why is AJAX called asynchronous? How does it accomplish communication asynchronously with the server?
It's asynchronous in that it doesn't lock up the browser. If you fire an Ajax request, the user can still work while the request is waiting for a response. When the server returns the response, a callback runs to handle it.
You can make the XMLHttpRequest synchronous if you want, and if you do, the browser locks up while the request is outstanding (so most of the time this is inappropriate)
It's asynchronous because the client and the server run independently of each other for the duration of the function call.
During a normal function call, you make the call, and the calling function doesn't get to execute again until the function call finishes and returns. The caller and the callee are always synchronized.
During an asynchronous function call, you make the call, and then control returns immediately to the caller. The callee then returns a value some indeterminate amount of time later. That "indeterminate amount of time" means the caller and callee are no longer synchronized, so it's asynchronous.
Simply put, it does not need to reload the whole page to get new information.
Think of a email client. You would not need to refresh the page to see new emails. Ajax just pulls the server every couple of minutes to see if there are new emails, if so display them
I.e. not "blocking", within the context of Javascript execution, as the response will be handled by an event loop.
The client and the server run independently of each other for the duration of the function call.
Normal function call - you make the call, and the calling function doesn't get to execute again until the function call finishes and returns. The caller and the callee are always synchronized.
Asynchronous function call - you make the call, and then control returns immediately to the caller. The callee then returns a value some undefined amount of time later. That "undefined amount of time" means the caller and callee are no longer synchronized, so it's asynchronous.
Synchronous always maintain sequence when called, but asynchronous is not maintain sequence.

Node.js: Connecting to a Server Using Sockets

I'm just starting to play with Node.js today, and thought I'd start with what I thought would be a simple script: Connecting to a server via sockets, and sending a bit of data, and receiving it back. I'm creating a command line utility. Nothing in the browser.
An example of a server would be memcached, beanstalkd, etc. It seems the net module is the right tool for the job, but I'm still a bit fuzzy on the Node.js way of doing things. Some help would be appreciated.
Update #1
Let me see if I can break this down in into a couple smaller questions. I hate even asking questions like this, but the Node.js documentation is very sparse, and most documentation written 6 months ago is already out dated.
1) So I can use net.stream.write() to send data to the remote server, but I don't know how to get a response back. I'm not even sure how to test when write() is finished, because it doesn't take a callback.
2) A few clues on how the whole event.emit thing works would be great. I think that's really the key stone I'm missing in those whole thing.
Update #2
Here's where I'm still confused on implementing a client program. Let me diagram a typical send request => get response system:
1) I bind callbacks to the net module to get responses and other events, including the necessary bindings to get a response from the server.
2) I use stream.write() to send a request to the server.
3) I then do nothing, because my bound "data" event will get the response from the server.
Here's where things get tricky. Suppose I call stream.write() twice before my bound "data" event is called. Now I have a problem. When the "data" event does happen, how do I know which of the 2 requests it's a response for? Am I guaranteed that responses will take place in the same order as requests? What if responses come back in a different order?
First of all, let's make clear what a EventEmitter is. JavaScript and therefore Node.js are asynchronous. That means, instead of having to wait for incoming connections on a server object, you add a listener to the object and pass it a callback function, which then, "as soon" as the event happens, gets executed.
There's still waiting here and there going on in the background but that has been abstracted away from you.
Let's take a look at this simple example:
// #1) create a new server object, and pass it a function as the callback
var server = net.createServer(function (stream) {
// #2) register a callback for the 'connect' event
stream.on('connect', function () {
stream.write('hello\r\n'); // as
});
// #3) register a callback for the 'data' event
stream.on('data', function (data) {
stream.write(data);
});
// #4) register a callback for the 'end' event
stream.on('end', function () {
stream.write('goodbye\r\n');
stream.end();
});
});
// #5) make the server listen on localhost:8124
server.listen(8124, 'localhost');
So we create the server and pass it the callback function, this function is not yet executed. Passing the function here is basically a shortcut for adding a listener for the connection event of the server object. After that we start the server at #5.
Now what happens in the case of an incoming connection?
Since the function we passed to createServer was bound to the connection event, it now gets executed.
It adds the connect, data and end event listeners to the stream object (which represents the individual connection) by hooking up callbacks for the events.
After that, the stream fires the connect event, therefore the function passed at #2 gets executed and writes hello\r\n to the stream. How does the function know which stream it should write to? Closures are the answer, the function inherits the scope it was created in, therefore inside the function stream is still referencing to the individual connection that triggered this very callback we're in right now.
Now the client sends some data over the connection, which makes the stream object call its data event, since we bound a function to this event at #3 we now echo the incoming data back to the client.
In case the client closes the connection, the function we've bound at #4 gets called, which writes goodbye\r\n and after that closes the connection from our side.
Does this make things a little bit more clear? Well it definitely makes the whole thing a lot easier. Node is, just as well as JavaScript is inside Browsers, single threaded. There's only one thing happening at a given point time.
To describe it simple, all these callbacks end up in a global queue and are then called one after another, so this queue may(abstracted) look like this:
| connection event for a new stream
| data event for stream #12
| callback set via setTimeout
v close event of yet another stream
These are now get executed top to bottom, nothing will ever happen in between those. There's no chance, that while you're doing something in the callback bound to the data event, something will other will happen and magically change the state of the system. Even if there is a new incoming connection on the server, its event will get queued up and it will have to wait until everything before it, including the data event you're currently in, finishes.

Categories

Resources