Chaining jQuery AJAX Calls (w/o Plugins)
Here’s the scenario: you need to make a series of AJAX calls to process a list of objects and each call is dependent on the results from the previous call. How can we structure this elegantly in jQuery without having to write massive chains or script callbacks?
An example would be using an AJAX based API to create a hierarchy of nested folders. Perhaps the user enters a string like “/path1/path2/path3” and multiple calls are needed to create “/path1″, then /path1/path2,” then “/path1/path2/path3”.
My friend John Peterson brought up jQuery deferred to me today and it clicked and my life is better for it.
Here’s an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
var parts = ["path1","path2","path3"]; // Output from string.split() var chain = $.Deferred(); // Create the root of the chain. var promise; // Placeholder for the promise // Build the chain for(var i = 0; i < parts.length; i++) { if(i == 0) promise = chain; // Pipe the response to the "next" function promise = promise.pipe(function(response) { var part = this.shift(); // Get the current part var root = ""; if(response) { root = response.newPath; } return $.ajax // MUST call return here. ({ type: "GET", url: "filemanager/create/" + root + part, context: this }); }) } promise.done(function(response){ // This handles the response from the final AJAX call }); chain.resolveWith(parts); // Execute the chain |
The general idea is that we start with a chain and “pipe” the output from each step to the next. When I execute the chain, I pass in the array as the argument on line 35.
This is necessary because referring to part[i] inside the function declared on line 11 will always yield “part3” . To work around this, we pass in the whole array of parts as the context to the chain. It becomes the “this” reference and we simply shift() a value off of the array to get the “current” item.
To pass the array to the next function in the chain, we simply set the context of the AJAX call to the “this” reference. Now, in the next handler in the chain, the “response” is the output of the previous AJAX call and the “this” reference is the “current” item in the array.
Of course, the final call — if you want to handle it — can be added to the chain using done() instead of pipe().
It’s a brilliant way of chaining multiple jQuery AJAX calls in a much more coherent manner!
1 Response
[…] can be downloaded here * Deferred Objects documentation * Fun With jQuery Deferred blog post * Chaining jQuery AJAX Calls (w/o Plugins) blog postRelated posts:jQuery Ajax Memory Leak in IE8Mobile API Requests with JSONFinding an […]