加载所有动态创建的图像时执行某些操作

时间:2014-05-24 20:03:00

标签: javascript jquery asynchronous javascript-events jquery-deferred

所以我要做的就是创建一个动态的图像墙。

我正在做的是:

  1. 调用API以获得一些响应。根据响应
  2. 创建对象数组
  3. 根据数组,为每个对象制作HTML元素,其中也包含img
  4. 创建所有这些HTML元素后,将其附加到DOM,并调用最终函数。
  5. 这是我到目前为止所做的事情(截断以得出重点):

    编辑:代码已经改变了一点。滚动到问题的底部以获取当前代码的链接。

    // based on one post, construct the html and return it
    function getOneHtml(post, w) {
      console.log("getting one html");
    
      var outerDiv = $("<div>", {class: "brick"});
      outerDiv.width(w);
    
      var img = $("<img />");
      img.attr("src", post.img_src);
    
      img.on('load', function() {
        console.log("img loaded");
        var ratio = this.width / w;
        h = this.height / ratio;
    
        $(this).css({'height': h});
    
        // ...
        // ...
        // create the element
    
        // an alternative I'm using for now is directly append
        // the created HTML onto the page, but that results
        // in a kinda messy interface.
        return outerDiv[0].outerHTML;
      });
    }
    
    // queries an api and then calls callback after everything is done
    function requestData(subreddit, callback) {
      // array of objects with link to image, post title, link to reddit
      posts = [];
    
      var w = $(window).innerWidth() / 3, 
          html = ''; // holds all of the inner HTML for all elements
    
      $.get("url here", function(data) {
        var arr = data.data.children;
    
        arr.forEach(function(res_post) {
          console.log("looping in requestData");
          // prepare a post object
          // ...
          // ...
    
          html += getOneHtml(post, w); // get the HTML for this post
        });
    
        // this should happen after everything else is done
        console.log("calling callback");
        callback(html);
      });
    }
    
    // complete the DOM
    function makeWall(html) {
      console.log("making wall");
      // do stuff
    }
    

    现在控制台中程序的跟踪是这样的:

    looping in requestData
    getting one html 
    looping in requestData
    getting one html 
    ... // bunch of times
    calling callback
    making wall
    (20) img loaded
    

    所以现在的问题是HTML在每个图像加载之前都没有准备好,所以它实际上并没有附加到DOM上。

    我如何确保按照我希望的顺序发生事情?我尝试将代码重构为更多的异步风格,但这不起作用(不是我最强的观点)。

    我也尝试过$.Deferred,但我不了解它,以及如何将其整合到我的代码中。

    感谢任何帮助。

    修改

    我认为看看我在做什么可能会有所帮助:http://karan.github.io/griddit/

    加载时,我希望首先加载图片,然后淡入。目前,它们会显示,然后隐藏然后淡入。这里是来源:https://github.com/karan/griddit/blob/gh-pages/js/main.js

    此外,如果向下滚动一页或两页,然后向上滚动,一些图像会显示在其他页面后面。

2 个答案:

答案 0 :(得分:0)

您可以使用.done().done() .done()中的说明明确说明如何将$.get()$.get( "test.php" ).done(function() { alert( "$.get succeeded" ); }); 一起使用。

它很简单:

.done()

具体...

如上面提供的API文档链接所示,您可以将$.get(url,handler).done(function(){console.log('calling callback')},callback); 个电话串联起来。

{{1}}

答案 1 :(得分:0)

注意,不确定所包含插件的功能,即#grid布局, css等图像widthheight#grid布局未解决,除了为了保证流量清晰而重新组合的现有作品。

以下仅用于满足// Do something when all dynamically created images have loaded要求。请参阅jsfiddle的控制台

另请注意,请参阅jsfiddle格式问题。为了测试片段,从原始帖子的链接中提取了2个插件。尝试了jsfiddle的TidyUp功能,它插入了换行符。

可能需要一些重新格式化;虽然目前的jsfiddle确实提供callback功能,但根据原始帖子。再次,请参阅控制台。谢谢分享。

更新

      $(function() {
        // the name of the last added post 
        var last_added = '';
        // to control the flow of loading during scroll var scrollLoad = true;
        var q = 'cats'; 
        var callbacks = $.Callbacks();
        // callback,
        // Do something when all dynamically created images have loaded
        var callback = function (cb) {
          return console.log( cb||$.now() )
        };
        callbacks.add(callback);
        function getOneHtml(post, w, count){ 
          var img = $("<img>", {
                        "src" : post.img_src,
                        "width" : w 
                    });
        img.on('load', function(e) { 
          var ratio = e.target.width / w;
          h = e.target.height / ratio;
          $(e.target).css('height',h)
        });

        var link = $("<a>", {
                        "href" : post.permalink,
                        "target" : "_blank",
                        "html" : img 
                   });

        var outerDiv = $("<div>", {
                        "class" : "brick",
                        "style" : "width:" + w
                       });

        $.when($(outerDiv).appendTo("#grid"),
        $(link),
        count)
        .then(function(div, _link, _count) {
          // `image` `fadeIn`; adjustable
          $(_link).appendTo($(div)).hide(0).fadeIn(2000);
          return _count
        })
        .always(function(_count){
          callbacks.fireWith(window, [_count + " images appended to grid at " + $.now()])
        });
        };

        function requestData(subreddit,callback) {
        //array of objects with link to image, post title,link to reddit
          posts=[];
          var w = $(window).innerWidth() / 3;
          html = '';
          $.ajax({
            type : 'get',
            url : "http://api.reddit.com/r/" + subreddit + "/hot.json?&after=" + last_added,
            beforeSend : function () {
              $("#searchterm").addClass("loadinggif");
            },
            complete : function () {
              $("#searchterm").removeClass("loadinggif");
            },
            success : function (data) {
              var arr = data.data.children;
              var count = null;
              arr.forEach(function(res_post) {
                if(!res_post.data.is_self&&(/\.(gif|jpg|jpeg|tiff|png)$/i).test(res_post.data.url)) {
                  // `images` count
                  ++count;
                  var post = {
        'title' : res_post.data.title,
        'img_src': res_post.data.url,
        'name' : res_post.data.name,
        'permalink': 'http://reddit.com' + res_post.data.permalink
        };
             getOneHtml(post, w, count);
        }
        last_added = res_post.data.name;
        });
        scrollLoad = true;
        // callback,
        // Do something when all dynamically created images have loaded
        // see `console`; adjustable
        callbacks.fireWith( window, [$(".brick img").size() + " appended to grid, callback at " + $.now()]);
        }});
        }

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                // function makeWall() {}
})

jsfiddle http://jsfiddle.net/guest271314/ggsY9/