开发者

Asynchronous confusion with ItemFileReadStore query

开发者 https://www.devze.com 2023-03-20 14:26 出处:网络
I want to save the results from a query using itemFileReadStore into an array called boxes, but the return value is empty (presumably because fetch is run asynchronously).

I want to save the results from a query using itemFileReadStore into an array called boxes, but the return value is empty (presumably because fetch is run asynchronously).

The gotItems function builds the array as I want it to, but I can't return that back to myself for any use! I could build the rest of my func开发者_JAVA技巧tionality into the gotItems part, but that would make my code unpretty.

How do I return an array for general use in my JavaScript from the gotItems function?

function getContentFile() {
  contentStore = new dojo.data.ItemFileReadStore({
    url: '../config/content.json',
preventCache : true 
  });

  var boxes = new Array();
  contentStore.fetch({query: {partner : 'enabled'}, onItem: gotItems });
  return boxes;
}

function gotItems(item ) {
  boxes.push( contentStore.getValue(item,'title') );
  console.log( boxes );
  return boxes;
}

dojo.addOnLoad( function() {
  boxes = getContentFile();
  console.log(boxes);
  fadeIn('header', 500, 0);
});


Welcome to the world of asynchronous operations.

You'll need to do it with the "continuation-style" programming. ItemFileReadStore's fetch operations is asynchronous -- as you already know by passing the gotItems continuation to it.

contentStore.fetch({query: {partner : 'enabled'}, onItem: gotItems }) will return immediately. Your boxes will be empty at that point (because JavaScript is single-threaded). gotItems is executed after data arrived and subsequent to the function passed to dojo.addOnLoad returning.

You have to put your handling code:

  console.log(boxes);
  fadeIn('header', 500, 0);

inside the continuation gotItems itself. For example, something like:

function gotItems(item ) {
  var boxes = [];
  dojo.forEach(item, function(box) {
    boxes.push( contentStore.getValue(box,'title') );
  });
  console.log(boxes);    // You probably need to store "boxes" somewhere instead of just logging it
  fadeIn('header', 500, 0);
}

Also, the data passed to onItems is an array, so you need to iterate it.


You don't have access to the results when the function returns because as you guessed, the fetch operation executes asynchronously.

You can either put the code that uses the results in your gotItems() function (as answered by Stephen), or you can use Deferreds and Promises. IMHO, that's a better alternative since it lets you organize your code better (once you get used to the idioms of dealing with promises, the code reads more naturally) and it allows you to transparently execute both synchronous and asynchronous operations.

See these two Dojo tutorials on the subject.

In your case, a possible solution involving deferreds would read like:

function getContentFile() {
  contentStore = new dojo.data.ItemFileReadStore({
    url: '../config/content.json',
    preventCache: true 
  });

  var dfd = new dojo.Deferred();
  var boxes = new Array();
  contentStore.fetch({
    query: { partner : 'enabled' },
    onItem: function(item) {
      boxes.push( contentStore.getValue(item,'title') );
    },
    onComplete: function() {
      // resolve the promise and execute the function in then()
      dfd.callback(boxes);
    }
  });
  return dfd;
}

dojo.addOnLoad( function() {
  getContentFile().then(function(boxes) {
    console.log(boxes);
    fadeIn('header', 500, 0);
  });
});
0

精彩评论

暂无评论...
验证码 换一张
取 消