Question

I am trying to get terms from a managed metadata service using JavaScript, Some of the terms has sub terms so I need to use nested deferred (jquery promises). following is my code.

$.when(GetTerms()).done(function (topMenu) {
     myDoElement.html(topMenu);
});
function GetTerms(){
   var dfd = $.Deferred();
   var arr1 = [];
   //some variables and code here
   clientCtx.load(terms);
   clientCtx.executeQueryAsync(Function.createDelegate(this, function (sender, args) {
      var termsEnumerator = terms.getEnumerator();
      while (termsEnumerator.moveNext()) {
         // here adds som html using arr1.push("");
         var currentTerm = termsEnumerator.get_current();
         $.when(GetSubTerms(currentTerm)).done(function (childItemsHtml) {
             //adding sub terms
              arr1.push(childItemsHtml);
         });             
       }
       //push closing html elements into arr1
       dfd.resolve(arr1.join(''));
   }),
   Function.createDelegate(this, function (sender, args) {
     dfd.reject(args.get_message());
   }));
   return dfd.promise();
 }

 function GetSubTerms(parent) {
     var dfdChild = $.Deferred();
     var arr2 = [];
     var childs = parent.get_terms();
     clientCtx.load(childs);
     clientCtx.executeQueryAsync(Function.createDelegate(this, function (sender, args) {
         //adding som html to arr1 using push
         var childsEnumerator = childs.getEnumerator();
         while (childsEnumerator.moveNext()) {
             var childTerm = childsEnumerator.get_current();
             //pushing elements into arr2
         }
         //pushing closing html elements into arr2
         dfdChild.resolve(arr1.join(''));
     }),
     Function.createDelegate(this, function (sender, args) {
         dfdChild.reject(args.get_message());
      }));
     return dfdChild.promise();
 }

If I don't use GetSubTerms it works good for top terms (parents) it returns all parents, but the problem is when I use GetSubTerms it returns only first parent.

Était-ce utile?

La solution

while (termsEnumerator.moveNext()) {
   // here adds som html using arr1.push("");
   var currentTerm = termsEnumerator.get_current();
   $.when(GetSubTerms(currentTerm)).done(function (childItemsHtml) {
     //adding sub terms
     arr1.push(childItemsHtml);
   });             
}
//push closing html elements into arr1
dfd.resolve(arr1.join(''))

That does not work. GetSubTerms is still asynchronous, so arr1 will not contain the childItemsHtmls when the dfd.resolve() is called. You will need to wait for the promises to finish before calling that! Do something like this:

function GetTerms(){
  var dfd = $.Deferred();
  // some variables and code here
  clientCtx.load(terms);
  clientCtx.executeQueryAsync(Function.createDelegate(this, function (sender, args) {
    dfd.resolve(terms.getEnumerator());
  }),
  Function.createDelegate(this, function (sender, args) {
    dfd.reject(args.get_message());
  }));

  return dfd.then(function(termsEnumerator) {
    var promises = [];
    while (termsEnumerator.moveNext()) {
      // here adds som html using promises.push($.when(""));
      var currentTerm = termsEnumerator.get_current();
      promises.push( GetSubTerms(currentTerm) );
    }
    //push closing html element promise into promises
    return $.when.apply($, promises).then(function() {
       var arr1 = $.map(arguments, function(args){return args[0];});
       //adding sub terms
       return arr1.join('');
    });
  });
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top