与ItemFileReadStore查询异步混淆

时间:2011-07-13 17:13:51

标签: dojo

我想将使用itemFileReadStore的查询结果保存到名为boxes的数组中,但返回值为空(可能是因为fetch是异步运行的)。

gotItems函数按照我的意愿构建数组,但我不能将它返回给自己任何用途!我可以将其余的功能构建到gotItems部分,但这会使我的代码不合适。

如何从gotItems函数返回我的JavaScript中常用的数组?

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);
});

2 个答案:

答案 0 :(得分:0)

欢迎来到异步操作的世界。

你需要使用“延续式”编程来完成它。 ItemFileReadStore的提取操作是异步的 - 正如您已经知道的那样,将gotItems延续传递给它。

contentStore.fetch({query: {partner : 'enabled'}, onItem: gotItems })会立即返回。此时boxes将为空(因为JavaScript是单线程的)。 gotItems在数据到达后执行,后续执行传递给dojo.addOnLoad返回的函数。

您必须输入处理代码:

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

在延续gotItems内部。例如,像:

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);
}

此外,传递给onItems的数据是一个数组,因此您需要迭代它。

答案 1 :(得分:0)

当函数返回时,您无权访问结果,因为您猜对了,fetch操作是异步执行的。

您可以将使用结果的代码放在gotItems()函数中(由Stephen回答),也可以使用Deferreds和Promises。恕我直言,这是一个更好的选择,因为它可以让你更好地组织你的代码(一旦习惯了处理promises的习惯用法,代码读取更自然),它允许你透明地执行同步和异步操作。

请参阅these two关于此主题的Dojo教程。

在您的情况下,涉及延迟的可能解决方案如下:

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);
  });
});