Asynchronous Operations

The functions URLFetchAsynchronous and URLSaveAsynchronous are used to download data in the background, while continuing to use the Wolfram Language for evaluations. Asynchronous function also lets you execute user-defined functions when data is received.

URLFetchAsynchronous and URLSaveAsynchronous both cause events to be triggered that can be handled by functions. For a basic example, to download the contents of a file in the background and be notified when the download completes.

eventFunc[_, "statuscode", _] := CreateDialog[{TextCell["Finished"], DefaultButton[]}];
URLSaveAsynchronous["", FileNameJoin[{$TemporaryDirectory, "index.html"}],

Both URLFetchAsynchronous and URLSaveAsynchronous can raise an event called that returns information about the data being downloaded and uploaded.

progress = {};
eventFunc[_, "progress", data_]:= AppendTo[progress, data];
", FileNameJoin[{$TemporaryDirectory, "index.html"}],
    eventFunc, "Progress"True]

The progress information can then be examined.

Part[progress, RandomInteger[Length[progress]]]

This information says that bytes had been downloaded of a total of bytes, while bytes were uploaded out of a total of bytes to be uploaded.

When using URLFetchAsynchronous, the event will return the content downloaded; if using URLSaveAsynchronous, an empty list will be returned by the event.

eventFunc[_, "data", data_]:= Print[FromCharacterCode[data]]
URLFetchAsynchronous["", eventFunc]

Both URLFetchAsynchronous and URLSaveAsynchronous raise an event if something goes wrong during the connection.

errorFunc[_, "error", _] := CreateDialog[{TextCell["Error Downloading Page"], 
URLFetchAsynchronous["http://notreal", errorFunc]

The asynchronous functionality makes it easy to create dynamic applications.

progress = 0.;
progressFunc[_, "progress", {now_, total_, _, _}]:= Quiet[progress = now/total]
URLFetchAsynchronous["", progressFunc, "Progress"True];

The Wolfram Language's powerful pattern matching can be used to easily write an event handler that receives multiple events.

multiEvent[_, "headers", headers_] := Print["Headers: ", headers];
multiEvent[_, "cookies", cookies_] := Print["Cookies: ", cookies];
multiEvent[_, "statuscode", statuscode_] := Print["StatusCode: ", statuscode];
multiEvent[_, "error", error_] := Print["Error:", error];

URLFetchAsynchronous["", multiEvent];

The first argument passed to an event function returns the AsynchronousTaskObject that raised the event; this is useful for running multiple tasks in the background.

asyncEvent[obj_, "statuscode", statuscode_] := Print[obj, " status code:", statuscode];
asyncEvent[obj_, "error", errorMsg_] := Print[obj, ": ", errorMsg];

URLFetchAsynchronous["", asyncEvent]
URLFetchAsynchronous["", asyncEvent]
URLFetchAsynchronous["http://notreal", asyncEvent]