| Flex 2 Developer's Guide >
Building User Interfaces for Flex Applications > Using Data Providers and Collections > Using remote data providers > Using paged remote data providers. |
|||
When you use a DataService class to get your remote data, you can have a collection that does not initially load all of its data on the client. By using this technique, you can prevent large amounts of data from traveling over the network and slowing down your application while that data is processed. The data that you get incrementally is referred to as paged data, and the data that has not yet been received is pending data.
When you retrieve paged data, your code might try to access pending data. In this case, the collection throws an ItemPendingError error.
Several Flex controls automatically catch and handle ItemPendingError errors thrown by the dataProvider collection so that your application does not have to manage the errors. These controls include: List, HorizontalList, TileList, DataGrid, Menu, and Tree.
Most other classes, including all chart controls, do not handle item pending errors, and you must write your own error handling code.
You must handle ItemPendingError errors in the following cases:
while loop in a try/catch block and continue calling until the iteration is complete. All classes that implement the ICollectionView and IList interfaces throw an ItemPendingError when Flex attempts to access paged collection data that is not yet available. The ItemPendingError class provides a techniques for finding out about the status of the requested data as follows:
addResponder() method that lets you specify an array of one or more IResponder objects. Flex framework provides an ItemResponder class that implements the IResponder interface, or you can create your own implementation class.try block.try block with a catch block with the following signature:
catch (e:ItemPendingError) {
responder1 = new ItemResponder(
// The result function
function (data:Object, token:Object=null) {
// Code to handle newly received data goes here.
}
// The fault function
function (info:Object, token:Object=null) {
// Code to handle a failure where data cannot become available
// goes here.
}
// The function must take an optional Object parameter; for
// information see ItemResponder in ActionScript 3.0 Language Reference.
);
e.addResponder(responder1);
The two functions that you pass in to the Responder constructor define the IResponder method implementations: the first function defines the implementation of the IResponder fault method, and the second function defines the implementation of the IResponder result method. The preceding example uses members of the Flex ItemResponder class as the responder objects, so it defines methods that take a second, optional parameter.
The following code shows how a function that iterates over a paged collection can handle ItemPendingError errors:
private var myCursor:IViewCursor;
private var total:int = 0;
// Iterate over the myView collection
private function iterate():void
{
if (myCursor == null)
myCursor = myView.createCursor();
// Put the code that moves the cursor in a try block.
try
{
while(!myCursor.afterLast)
{
total += myCursor.current.amount;
myCursor.moveNext();
}
trace('Total amount is:', total);
}
// The catch block handles the error generated when the requested data
// is pending.
catch (e:ItemPendingError)
{
// Create a new Responder object and assign it to the error object's
// responder property.
responder = new ItemResponder(
// Define a function to handle case where the data becomes available.
function (data:Object, token:Object=null) {
myCursor.moveNext();
iterate();
},
// Define a function to handle case where a "real" error occurs.
function (info:Object, token:Object=null) {
trace('fault when retrieving data', info.toString());
});
}
}
Almost all cursor functions may throw ItemPendingErrors. It is worth noting that if an ItemPendingError is thrown the cursor will remain at its last known good value, meaning that if you call moveNext() and the error is thrown the cursor will have remained on the old value of current. A smaller number of methods will throw an error on IList (getItemAt and getIndexOf primarily), check the ASDoc for details.
Data might not always be loaded sequentially, so it is possible that you will be in the middle of an ICollectionView and will movePrevious with your cursor and will encounter an ItemPendingError.
If your application uses a control, such as a chart control, that requires the data provider to contain the complete data set, your application must ensure that all the data in a collection is available before assigning the control's dataProvider property. In most cases, you can do this by configuring the DataService not to use paging. However, in some cases, such as those where you use the same Data Management Service destination for multiple purposes in your Flex application, you might need to use paged data in your control.
One technique for using paged data in a control that requires complete data is to use the IList interface toArray() method. This method attempts to load all the data in its parameter object into an Array. If not all the data is available, it throws an ItemPendingError error, and you can handle the error as described in Handling ItemPendingError errors. Alternatively, you can iterate from the beginning to the end of the data before using it in the control.
The following example shows this use to ensure that a paged data provider (specified by the theDP variable) has complete data before using it in a chart control:
private function loadDP():void
{
var cursor:IViewCursor = theDP.createCursor();
try
{
while (cursor.moveNext()) {}
chart.dataProvider = theDP;
}
catch (e:ItemPendingError)
{
e.addResponder(new ItemResponder(
function (result:Object, token:Object=null)
{
loadDP();
},
function (fault:Object, token:Object=null)
{
trace('Error while loading');
}
));
cursor = null; //Might as well let it garbage collect.
}
}
Flex 2.01