【问题标题】:make .each() wait for converting element to DataURL使 .each() 等待将元素转换为 DataURL
【发布时间】:2017-08-31 16:00:19
【问题描述】:

我正在使用html2canvas 转换html2canvas,

我正在使用.each 解析html,然后将元素传递给html2canvas。在元素转换为DataURL 之后。我将它推送到数组content

$('.itinerary-section-detail').each(function( index, element ) { 
                 setTimeout(function() {
                   console.log(element);
                       html2canvas(element).then(function(canvas) {
                            element.appendChild(canvas);
                             elem  = canvas.toDataURL();
                              var item = {};
                              item["image"] = elem;
                              item["width"] = 595;
                              content.push(item);
                          }); 
                  }, 4000);
            });

但问题在于将元素转换为 DataURL 的时间会有所不同。这就是为什么元素的顺序是随机的。所以我需要等到一个元素被转换为DataURL,将它推入content数组,然后从.each进入下一个元素。

请在这里给我建议一个方法。试过setTimeout,没用。

【问题讨论】:

  • 看来.toDataURL()是同步的toDataURL acting async
  • 您可以做的是为每次异步启动增加一个变量(我猜是html2canvas)并将其传递给回调,以便元素知道它必须放在哪个索引中数组
  • 不是想说,我其实是在说;)添加了一个例子
  • 我认为this answer昨天没用?
  • @JaromandaX 和昨天不一样了。这是关于 .each 并在其中将元素转换为 DataURL 和问题排序元素

标签: javascript jquery promise html2canvas


【解决方案1】:

您不能只循环异步元素,因为它们不会暂停循环。相反,您可以构造一组 Promise 并使用 $.when。然后,一旦所有承诺解决,您提供的回调将被调用:

var promises = $('.itinerary-section-detail').map(function(index, element) {
  console.log(element)
  return html2canvas(element).then(function(canvas) {
      element.appendChild(canvas)
      var elem = canvas.toDataURL()

      return {
        image: elem,
        width: 595
      }
    })
}).get()

$.when.apply(null, promises).then(function() {
  var content = [].slice.call(arguments)
  console.log(content)
})

【讨论】:

  • 感谢您的回答,如何将返回的对象推送到$.when 中的content 数组?对不起这个问题,我不知道这一切
  • 仍然得到与console.log('done', arguments);相同的结果
  • 我的意思是我已经发布了问题var item = {}; item["image"] = elem; item["width"] = 595; content.push(item); how can I do this in $.when`我得到ZoneAwarePromise的数组
  • 你不需要推送任何东西,内容数组将在我的回答中发布的回调中可用。
  • content 数组显示[ZoneAwarePromise, ZoneAwarePromise, ZoneAwarePromise, ZoneAwarePromise],我需要[{image:elem1,width:595},{image:elem2,width:595},{image:elem3,width:595}],我怎样才能得到这个?
【解决方案2】:

这显示了我在评论中所说的话。我用超时和随机延迟模拟了异步。

在示例中,IIFE 仅用于跟踪 index,因为它会在异步回调中丢失(您也可以将异步调用包装在存储值的函数中)

结果finish不排序,但数组结果是。

var content = [];

$('div.kadd').each(function( index, element ) { 
    console.log('launching: ' + element.innerHTML);
    (function(i){ setTimeout(function() {
        console.log('finishing: ' + element.innerHTML);
        content[i] = element.innerHTML;
    }, (Math.random() * 100) + 1); })(index);
});

setTimeout(function() {
    console.log('result: ', content);
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="kadd">A</div>
<div class="kadd">B</div>
<div class="kadd">C</div>
<div class="kadd">D</div>
<div class="kadd">E</div>
<div class="kadd">F</div>
<div class="kadd">G</div>

【讨论】:

  • 感谢您的回答,我无法添加setTimeout(),因为元素可能太多。这是一个我有更多相同的功能,所以需要对所有人都做同样的事情,使用setTimeout会花费太多时间
  • setTimeout 只是一个异步示例,在您的情况下,您只需将其替换为 html2canvas()。确实,我的示例缺少知道所有异步调用已结束的代码(这可以通过承诺来完成,我使用了全局超时)。顺便说一句,promise 本身并不能保证结果会按顺序到达,这就是我回答的目的,这只是说明了有序的结果
猜你喜欢
  • 2019-08-05
  • 2017-03-23
  • 2014-10-30
  • 1970-01-01
  • 2018-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-22
相关资源
最近更新 更多