title: Lazy loading dojo tree powered by JsonRestStore and jsonp
body: <p>I am trying to implement a cross domain, lazy loading tree using the Dojo toolkit.  So far I have the top level nodes displaying correctly, but on clicking the expando I get a "deferred has already been resolved" error and I'm not sure why.  I can see that the fetch method seems to be working by looking at the firebug network tab.  I think my problem is within my _processResults method, perhaps something to do with the defining of the _loadObject within it...</p>
  
  <p>I feel like I should know Dojo better given all the time I've spent trying to understand it.  But alas, its quite a beast... I've seen some mention of JSONP and lazyloading not working in one of the sitepen blogs (<a href="http://www.sitepen.com/blog/2008/06/25/web-service-data-store/" rel="nofollow">http://www.sitepen.com/blog/2008/06/25/web-service-data-store/</a> ), but it doesn't mention why it shouldn't be possible other than JSONP being asyncronus.  If Dojo is going to just stuff incoming json data into the store, I don't understand why that should matter.</p>
  
  <p>Perhaps it has to do with my formating of the data - another example on sitepen (<a href="http://www.sitepen.com/blog/2010/01/27/efficient-lazy-loading-of-a-tree/" rel="nofollow">http://www.sitepen.com/blog/2010/01/27/efficient-lazy-loading-of-a-tree/</a>) using the jsonreststore doesnt load an item until you expand a node, whereas my format loads the item but doesnt load the children nodes until you expand it... </p>
  
  <p>Without further ado, here is ta codez... </p>
  
  <pre><code>&lt;script type="text/javascript"&gt;
  dojoConfig = {
  parseOnLoad: true,
  isDebug: true,
  usePlainJson: true  
  };
  &lt;/script&gt;
  &lt;script type="text/javascript" src="scripts/dojo_16/dojo/dojo.js"&gt;&lt;/script&gt;
  
  &lt;script type="text/javascript"&gt;
      dojo.require("dojo.parser");
      dojo.require("dojo.io.script");
      dojo.require("dojox.rpc.Service");
      dojo.require("dojox.data.ServiceStore");                    
      dojo.require("dijit.tree.ForestStoreModel");                    
      dojo.require("dijit.Tree");         
  
      dojo.addOnLoad(function(){
  
          var mySmd = {
                  "SMDVersion": "2.0",
                  "id": "http://urlbehindfirewall/testtree/", 
                  "description": "This is the service to get to the finder app backend data",
  
                  transport: "JSONP",
                  envelope: "URL",
                  additionalParameters: true,
                  target: "http://urlbehindfirewall/testtree/",               
  
                  services: {
                      "getChildrenNodes": {
                      "target": "getChildrenNodes.php",
                          parameters: [
                              { name: "nodeId", type: "integer"}                             
                          ]
                      }
                  }
  
          };
  
          var myService = new dojox.rpc.Service(mySmd);
  
          var myStoreParams = {               
              service : myService.getChildrenNodes,
              idAttribute : "Node_Id",
              labelAttribute : "Display_Name",
              _processResults: function(results, def){                                        
                  var _thisStore = this;
                  for(i in results){
                      results[i]._loadObject = function(callback){
                          _thisStore.fetch({
                          query: { nodeId: this.Node_Id },
                          onItem: callback
                          });
                      delete this._loadObject;
                      };
                  }                   
                  return {totalCount: results.length, items: results};                                                
              }
          };
  
  
          var myStore = new dojox.data.ServiceStore(myStoreParams);
  
          //create forestTreeModel
          var treeModelParams = {
              store: myStore,
              deferItemLoadingUntilExpand: true,
              childrenAttrs: ["Children_Nodes"],              
              rootId : 1,
              query: 1
              };
  
          var treeModel = new dijit.tree.ForestStoreModel(treeModelParams);
  
          var myTree = new dijit.Tree({
              model: treeModel,
              id: "myTree",
              showRoot: false 
              });
  
          dojo.byId("treeContainer").appendChild(myTree.domNode);
          myTree.startup();                   
      });
  
  &lt;/script&gt;
  </code></pre>
  
  <p>And here is an example of the json data structure: unfortunately the service is behind a network firewall currently... i will work on putting up a public version to demonstrate in a bit.  Meanwhile, this is the response for searching on the root node, node 1:</p>
  
  <pre><code>    [
     {
        "Node_Id":"2",
        "Display_Name":"LeftNode:2",
        "Secondary_Names":"Parent:1",
        "Obi_Id":"10002",
        "Children_Nodes":[
  
        ],
        "Has_Children":true,
        "Child_Node_Ids":[
           "5",
           "6",
           "7",
           "8"
        ]
     },
     {
        "Node_Id":"3",
        "Display_Name":"Middle Node:3",
        "Secondary_Names":"Parent:1",
        "Obi_Id":"10003",
        "Children_Nodes":[
  
        ],
        "Has_Children":true,
        "Child_Node_Ids":[
           "9",
           "10"
        ]
     },
     {
        "Node_Id":"4",
        "Display_Name":"Right Node:4",
        "Secondary_Names":"Parent:1",
        "Obi_Id":"10004",
        "Children_Nodes":[
  
        ],
        "Has_Children":true,
        "Child_Node_Ids":[
           "11",
           "12"
        ]
     }
  ]
  </code></pre>
  
  <p>Expanding any of the above nodes would then get the children of that node - so 2 would get the node array of 5,6,7,8 .  (It may not be necessary to have the Child_Node_Ids and Children_Nodes for the current implementation, but shouldn't be breaking anything no?)</p>
  
  <p>So I'm sure eyes are glazing by now, to restate the issue - what is creating this "deferred has already been resolved" error?  Is lazy loading in a tree possible with JSONP?  Would a different json structure solve my lazy loading problems?  Is it possible to reformat my data within dojo so that it works? (I thought that was the point to the _processResults method... ) Are there any publicly accessible tree dataservices out there to practice on?</p>
  
  <p>Thanks everyone!</p>