2017-02-11 2 views
0

С фоном в объектно-ориентированных языках Я пытаюсь изучить некоторые jquery и обернуть голову вокруг асинхронных вызовов. Мое намерение состояло в том, чтобы создать объект javascript, чтобы содержать результаты асинхронных вызовов api, и иметь возможность спросить упомянутый объект, если он был загружен.

Я пытаюсь сделать это с использованием Deferred из jquery, и у меня нет проблем с тем, чтобы получить отрывки для работы, как в примерах документирования, но он не будет выполняться в том порядке, который я ожидаю, когда я помещаю Deferred внутри моего класс.

Как создать javascript-объекты с $ .Deferred как переменными-членами?

(тайм-ауты в моем прикрепленного коде, чтобы имитировать задержки в API вызовов)

<!DOCTYPE html> 
<html> 
    <body> 
    <script src="jquery-3.1.1.js"></script> 
    <script> 
     //top level 
     var isdone = false; 
     var def = $.Deferred(); 

     $.when(def).done(function() { 
      var msg = "checking topLevel isdone " + isdone; 
      console.log(msg); 
      $("body").append("<p>" + msg + "</p>"); 
     }) 

     var delayedCall = function() { 
      setTimeout(function() { 
      //resolve after 5 seconds 
      isdone = true; 
      def.resolve(); 
      }, 1000); 
     } 
     delayedCall(); 



     //inside function 
     function DelayedObject() 
     { 
      this.defThis = $.Deferred(); 
      var defVar = $.Deferred(); 
      this.delayedObjCall = function() 
      { 
      setTimeout(function() 
      { 
       //resolve after 5 seconds 
       isdone = true; 
       this.def.resolve(); 
      }, 1000); 
      } 
      this.delayedObjCall(); 
      this.getStatusThis = function() 
      { 
      return this.def; 
      } 
      this.getStatusVar = function() 
      { 
      return this.def; 
      } 
     } 

     delObj = new DelayedObject(); 
     $.when(delObj.getStatusThis()).done(function() { 
      var msg = "checking delObj (this) isdone " + isdone; 
      console.log(msg) 
      $("body").append("<p>" + msg + "</p>"); 
     }); 
     $.when(delObj.getStatusVar()).done(function() { 
      var msg = "checking delObj (var) isdone " + isdone; 
      $("body").append("<p>" + msg + "</p>"); 
      console.log(msg) 
     }); 

     $(window).on("load", function() 
     { 
      var msg = "<p>" + " Page loaded " + "</p>"; 
      $("body").append(msg); 
      console.log(msg); 
     }); 
     </script> 
    </body> 
    </html> 

Result

checking delObj (this) isdone false 

checking delObj (var) isdone false 

Page loaded 

checking topLevel isdone true 
+0

'this.def',' this.defThis', 'defVar' ??? Вы хотите * одно * отложить. – Bergi

+0

Я знаю, я включил несколько здесь, чтобы лучше проиллюстрировать мою проблему. Могли бы упомянуть, что в комментарии к коду, хотя – Schaki

ответ

1

Некоторые вопросы:

  • Вы обращаетесь к неправильным объектам/переменных в некоторых местах (this.def не существует, this.defThis и defVar никогда не используются)

  • this не определен в функции обратного вызова тайм-аута (или window в неаккуратного режиме), поэтому необходимо использовать решение для этого (несколько возможностей, например, bind)

  • Вы никогда не решить defVar

  • Вы используете один isdone переменные, так что понимают, что когда он установлен в true остается true и мало говорит о других обещаниях.

Здесь корректируется код (упрощенный: опуская изменение содержимого документа):

var isdone = false; 
 
var def = $.Deferred(); 
 

 
$.when(def).done(function() { 
 
    console.log("checking topLevel isdone " + isdone); 
 
    isdone = false; // set back to false 
 
}); 
 

 
var delayedCall = function() { 
 
    setTimeout(function() { 
 
    isdone = true; 
 
    def.resolve(); 
 
    }, 500); // Half a second 
 
} 
 
delayedCall(); 
 

 
//inside function 
 
function DelayedObject() { 
 
    this.defThis = $.Deferred(); 
 
    var defVar = $.Deferred(); 
 
    this.delayedObjCall = function() { 
 
    setTimeout(function() { 
 
     //resolve after 5 seconds 
 
     isdone = true; 
 
     this.defThis.resolve(); // refer to the correct object 
 
    }.bind(this), 1000); // provide the correct context with bind 
 
    // Also resolve the other deferred: 
 
    setTimeout(function() { 
 
     //resolve after 5 seconds 
 
     isdone = true; 
 
     defVar.resolve(); 
 
    }.bind(this), 1500); //... a bit later 
 
    } 
 
    this.delayedObjCall(); 
 
    this.getStatusThis = function() { 
 
    return this.defThis; // return correct object 
 
    } 
 
    this.getStatusVar = function() { 
 
    return defVar; // return correct object 
 
    } 
 
} 
 

 
delObj = new DelayedObject(); 
 
$.when(delObj.getStatusThis()).done(function() { 
 
    console.log("checking delObj (this) isdone " + isdone); 
 
    isdone = false; // set back to false 
 
}); 
 
$.when(delObj.getStatusVar()).done(function() { 
 
    console.log('checking delObj (var) isdone ' + isdone) 
 
    isdone = false; // set back to false 
 
}); 
 

 
$(window).on("load", function() { 
 
    console.log('Page loaded'); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

+0

bind() был тем, что я искал, thx! – Schaki