Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 从指令到服务的角度队列操作_Javascript_Angularjs - Fatal编程技术网

Javascript 从指令到服务的角度队列操作

Javascript 从指令到服务的角度队列操作,javascript,angularjs,Javascript,Angularjs,我正试图更好地理解如何正确地在Angular中编码,并且正在编写自己的自定义模块,以便更好地理解应该如何工作 我有一个由图像和指令组成的HTML标记,即 <img ng-if="!post.tooBig" mydirective resize="0" ng-src="/img/@{{post.Content}}"> 想法是这样的:如果图像的文件名中附加了small,我知道它是一个缩略图。我想在后台加载它的大版本(同一个文件,没有附加的小文件),这样它就可以用于lightbox了 这

我正试图更好地理解如何正确地在Angular中编码,并且正在编写自己的自定义模块,以便更好地理解应该如何工作

我有一个由图像和指令组成的HTML标记,即

<img ng-if="!post.tooBig" mydirective resize="0" ng-src="/img/@{{post.Content}}">
想法是这样的:如果图像的文件名中附加了
small
,我知道它是一个缩略图。我想在后台加载它的大版本(同一个文件,没有附加的小文件),这样它就可以用于lightbox了

这可以正常工作,但问题是,当我设置
bigImage.src=source.replace(“small.”,“)时,我正在编译
中完成所有工作它会立即启动,如果页面上有许多
小的
图像,它会导致页面速度减慢,因为正在进行的加载

因此,我想使用
$q
使其一次加载一个图像

所以行动吧

 var bigImage = new Image();
 bigImage.src = source.replace("small.",".");
变成承诺。在指令中这样做是最佳实践吗?我的理解是这样做是没有意义的,我应该使用服务,但我不知道如何做到这一点。我可以更多地使用它,但我希望有更多经验的人能够指导我,像这样的最佳实践,以及类似工作流的代码示例,谢谢

编辑:

指令:

.directive('mydirective', [
           '$animate','$mediaStack',
  function($animate,$mediaStack) {
  return {
    restrict: 'A',
    compile: function(tElement, tAttrs) {
        return loader;
    }
  };

    function loader(scope, element, attrs) {
      var source = attrs.ngSrc;
      var tooLoadBig = parseInt(attrs.resize);
      if(tooLoadBig){
        /*var bigImage = new Image();
        bigImage.src = source.replace("small.",".");*/
        $mediaStack.load(source);
      }
      }
}])
我的服务:

.factory('$mediaStack', [
             '$animate', '$timeout', '$document', '$compile', '$rootScope',
             '$q',
             '$injector',
    function($animate ,  $timeout ,  $document ,  $compile ,  $rootScope ,
              $q,
              $injector) {
      var OPENED_MEDIA_CLASS = 'media-open';
      var theImages = [];
      $mediaStack = {};
      $mediaStack.load = function(source){
          theImages.push(source);
      };
      $mediaStack.loadRequest   = function(theImages) {

                          deferred.resolve(function(){
                          var bigImage = new Image();
                          bigImage.src = theImages[0].replace("small.",".");
                          });
                          return deferred.promise;
                        }

                        /*var promise = asyncGreet('Robin Hood');
                        promise.then(function(greeting) {
                          alert('Success: ' + greeting);
                        }, function(reason) {
                          alert('Failed: ' + reason);
                        }, function(update) {
                          alert('Got notification: ' + update);
                        });*/
                        //above from docs
      }
      return $mediaStack;
    }])
这是因为它将图像URL获取到服务中的一个数组中,因此我拥有该数组中的所有图像,如何基于该数组正确使用
$q
。我已经开始学习了,但是大部分的
$mediaStack.loadRequest
都是基于文档的,我不知道在这种情况下如何有效地使用它

编辑2:

我的服务是:

    .factory('$mediaStack', [
                 '$animate', '$timeout', '$document', '$compile', '$rootScope',
                 '$q',
                 '$injector',
        function($animate ,  $timeout ,  $document ,  $compile ,  $rootScope ,
                  $q,
                  $injector) {
           var OPENED_MEDIA_CLASS = 'media-open';
      var theImages = [];
      var theLoadedImages = [];
      var thePromises = [];
      var loading = false;
      $mediaStack = {};
      $mediaStack.load = function(source){
          theImages.push(source);
          var mainDeferred = $q.defer();
         if(loading)
         {
             thePromises.push(mainDeferred.promise);
             console.log(thePromises);
             $mediaStack.myRaceFn(thePromises).then(function() { 
             console.log("Fire!");
             loading=true;
            $mediaStack.loadRequest(theImages[0]).then(function(bigImage){ 
          console.log(bigImage);
            theImages.shift();
            theLoadedImages.push(bigImage);
            loading = false;
          mainDeferred.resolve(); 
        });
      });
         }
         if(!loading)
         {
            loading = true;
            $mediaStack.loadRequest(theImages[0]).then(function(bigImage){
            console.log(bigImage);
            theImages.shift();
            theLoadedImages.push(bigImage);
            loading = false;
            mainDeferred.resolve();         
            });

         }
           }
      $mediaStack.loadRequest = function(source){
                          var deferred = $q.defer();
                          var bigImage = new Image();
                          bigImage.src = source.replace("small.",".");
                          bigImage.onload = function() {
                          deferred.resolve(bigImage);
                          }
                           return deferred.promise;
      }
      //.race implementation in old angular
      $mediaStack.myRaceFn = function (promises){
   return $q(function(resolve, reject) { 
     promises.forEach(function(promise) {
       console.log(promise);
       promise.then(resolve, reject);
     });
   });
}
//.race implementation in old angular
      return $mediaStack;
        }])
我非常接近,我看到了一系列的承诺,但我从来没有达到能够再次发射它们的程度,所以我有10张图片,我得到了9个承诺。我如何解雇他们

我以为会发生在这里:

$mediaStack.myRaceFn(thePromises).then(function() { 
console.log("Fire!");
loading=true;
$mediaStack.loadRequest(theImages[0]).then(function(bigImage){ 
但是我从来没有得到过
console.log()

相反,我在
$mediaStack.myRaceFn()
中获得控制台消息,向我显示每个承诺(最后是9个),但它们只是坐在那里?我错过了一些东西


我想我可能太早了…

我想,你的直觉很好。您需要一个服务来处理图像请求。请记住,浏览器仅限于向单个服务器/代理发送多个并发请求()

理论上,您可以创建一个promise,并通过双向绑定甚至使用属性驱动加载来公开它。比如:

HTML:

但我认为,这样的服务会更好。您可以从这一点决定加载内容和加载时间。它不会局限于UI组件,您可以加载更大的图像,而不仅仅是从指令上下文。 因此,在服务中,基本代码是:

module.factory('$mediaStack',['$q',function($q){//首先,您不需要所有这些依赖项,请保持列表简短
var imgDict={};//图像字典,我们将在其中信守承诺并加载图像
var loadingNow=0;
函数loadImage(img){
//发送请求并返回承诺
var deferred=$q.deferred();
var bigImage=新图像();
bigImage.onload=函数(){
延迟解析(bigImage);
}
bigImage.src=source.replace(“小“,”);
回报。承诺;
}
var$mediaStack=函数(img){
var deferred=$q.deferred();//主延迟任务
如果(loadingNow>4){//如果我们正在加载5个或更多图像,请将任务推迟到加载其中一个图像为止
var promissions=[];//承诺数组,现在正在加载的图像列表
Object.key(imgDict).forEach(函数(key){
如果(!(imgDict[key]instanceof Element)){//检查字典中的项是承诺还是加载的图像
promises.push(imgDict[key]);//如果是承诺,请将其添加到列表中
}
});
$q.race(promissions).then(function(){//使用列表创建一个竞赛:当一个承诺解决时(加载图像),我们可以再次启动我们的函数(我们可能同时加载的图像少于5个)
$mediaStack(img)。然后(函数(数据){//再次调用该函数
resolve(data);//当我们返回一个承诺表单时,我们必须解析主延迟对象
});
});
}
如果(!(img in imgDict)){//图像尚未加载时
loadingNow++;//增加正在加载的图像数量
imgDict[img]=loadImage(img)。然后(函数(imgDOM){//并加载映像
imgDict[img]=imgDOM;
deferred.resolve(imgDOM);//加载后解析主延迟任务
现在加载--;
});
}否则{
延期。解决(imgDict[img]);
}
return deferred.promise;//对主延迟任务的承诺
}
返回$mediaStack;

}]);我认为,你的直觉很好。您需要一个服务来处理图像请求。请记住,浏览器仅限于向单个服务器/代理发送多个并发请求()

理论上,您可以创建一个promise,并通过双向绑定甚至使用属性驱动加载来公开它。比如:

HTML:

但我认为,这样的服务会更好。您可以从这一点决定加载内容和加载时间。它不会局限于UI组件,您可以加载更大的图像,而不仅仅是从指令上下文。 因此,在服务中,基本代码是:

module.factory('$mediaStack',['$q',function($q){//首先,您不需要所有这些依赖项,请保持列表简短
var imgDict={};//图像字典,我们将在其中信守承诺并加载图像
var loadingNow=0;
函数loadImage(img){
//发送请求并返回承诺
var deferred=$q.deferred();
var bigImage=新图像();
大形象。
$mediaStack.myRaceFn(thePromises).then(function() { 
console.log("Fire!");
loading=true;
$mediaStack.loadRequest(theImages[0]).then(function(bigImage){ 
<img mydirective="booleanValue" />
$scope.$watch('mydirective', function (newVal, oldVal) {
  if (newVal === true) {
    //perform the load
  }
});
    .factory('$mediaStack', [
             '$animate', '$timeout', '$document', '$compile', '$rootScope',
             '$q',
             '$injector',
    function($animate ,  $timeout ,  $document ,  $compile ,  $rootScope ,
              $q,
              $injector) {
      var OPENED_MEDIA_CLASS = 'media-open';
      var theImages = [];
      var theLoadedImages = [];
      var thePromises = [];
      var loading = false;
      $mediaStack = {};
      $mediaStack.load = function(source){
          if(source)
          {
          theImages.push(source);
          }
          var mainDeferred = $q.defer();
         if(loading)
         {
             thePromises.push(mainDeferred.promise);
             console.log(thePromises);
             $mediaStack.myRaceFn(thePromises).then(function() { 
             console.log("Fire!");
             loading=true;
            $mediaStack.loadRequest(theImages[0]).then(function(bigImage){ 
          console.log(bigImage);
            theImages.shift();
            theLoadedImages.push(bigImage);
            loading = false;
          //mainDeferred.resolve(); 
        });
      });
         }
         if(!loading)
         {
            loading = true;
            $mediaStack.loadRequest(theImages[0]).then(function(bigImage){
            console.log(bigImage);
            theImages.shift();
            theLoadedImages.push(bigImage);
            loading = false;
            if(theImages.length>0)
            {
            $mediaStack.load();     
            };          
            });

         }
           }
      $mediaStack.loadRequest = function(source){
                          var deferred = $q.defer();
                          var bigImage = new Image();
                          bigImage.src = source.replace("small.",".");
                          bigImage.onload = function() {
                          deferred.resolve(bigImage);
                          }
                           return deferred.promise;
      }
      //.race implementation in old angular
      $mediaStack.myRaceFn = function (promises){
   return $q(function(resolve, reject) { 
     promises.forEach(function(promise) {
       console.log(promise);
       promise.then(resolve, reject);
     });
   });
}
//.race implementation in old angular
      return $mediaStack;
    }])