Artificial Latency: A How To
So you have a client side app written in javascript and you are worried about latency. This latency is inevitable and can arise in loading assets as well as in AJAX calls. Now you have taken care of those situations and have written your app to behave gracefully in those waiting periods.
The problem
However, how do you test the behavior of your app in these cases when all you have is blazing fast access to the Internet?
We would want the test to be easy to turn on an off.
Ideally, it would be as simple as changing only the source code of the app (the HTML or the
apiPrefix
) and reloading the browser.
The setup
Your development setup probably looks like this:
In the normal no-artificial-delay situation, your app is served by a Local Webserver:
The Local Backend might be merged with the Local WebServer (like in Rails or Jetty) or it could be running separately (as depicted). The backend may be running locally or the web-server may be proxying requests to a sandbox backend hosted on the Internet. Optionally, your app may load some assets from the internet directly.
The remote assets
Loading of those assets is relatively easy to delay and test.
You can use a delay proxy by replacing the URL of your resource
http://remote.com/asset.png
byhttp://deelay.me/5000/http://remote.com/asset.png
* Note the double ee
in deelay
.
Deelay.me is an delay proxy which will redirect the browser to the original URL after sufficient delay.
However, Deelay.me has some short-comings. You cannot access resources over https
and it does not set the correct CORS headers. I am working on a project receive-in to address these issues.
Update: It turns out that what I was trying to do via CORS header is explicitly not allowed in the spec. However, the spec may allow this behavior if a compelling use-case comes up.
The local assets
You can take a similar approach here.
I would recommend running OpenResty (configured --with-luajit
). Then you can configure your nginx
to delay all paths with the prefix /delay/([0-9]+)/
with the following location
block:
Now, you will be able to introduce a 5 sec delay by replacing an API call to
/api/user/1
by/delay/5000/api/user/1
.
Hack: You can make this work for remote servers too if you edit the hosts
file and redirect request to the Internet to your local machine.
Other solutions
If you do not want to go through the trouble of installing OpenResty and running a local webserver, then one of the following solutions may work for you.
The backend
If you are running your backend locally, then you can delay individual requests on your backend itself:
If you are developing an integrated web-server + backend application, then this might be the easiest option for you. However, the server may not allow you to easily add latency while serving files from the HDD.
The network interface
If you are on linux then you can slow down your lo
connection. However, but this slows down everything, which may be too much if you want to test how delay affects one request.
On Mac OSX
, there is a Network Link Conditioner tool which can slow down the connection for you. It can simulate 3G, WiFi, high latency DNS, etc. connections as well, which can be great to assess the behavior of your app on those networks. However, this too slows all the connections, which is not what we want while testing for the slow response for certain requests.
Delay in the local-webserver
Often the Local WebServer will allow usage of some middleware to delay the requests:
Grunt
If you are using grunt
as part of your workflow and using grunt-contrib-connect
or grunt-express
to serve your app, then you can use grunt-connect-delay
to delay your requests by 5 secs by prefixing them with /delay/5000/
. I have written an example app while using it.
For an example of how the plugin can be of use, have you ever thought what would happen if your fonts loaded very slowly?
Other resources
If there are delays, then you should always give users a sense of progress. These resources will help you do that: