延期承诺词典

A dictionary of deferred promises

我需要用图像构建 PDF。我认为可以提供指向本地存储文件的链接,但是(请纠正我,我会很高兴)事实证明 PDFmake 只能处理 data:URI 编码图像。
所以现在我必须转换图像,但必须先加载它们,否则我将转换为空白。

想法是将 PDF 建筑代码放在
的括号中 $.when.apply(null, imgData).done(function() { });
据我所知,图像可以随机加载,所以为了防止弄乱它们的顺序,我将它们放入字典中,其中每个值的键是来自初始 imgSources 数组的索引。
现在,我是第一次使用Deferred class 和$.when,所以请纠正我的错误用法。

function toDataUrl(src) {
    var img = new Image(),
    deferred = $.Deferred();
    img.crossOrigin = 'Anonymous';
    img.onload = function() {
        var canvas = document.createElement('CANVAS');
        var ctx = canvas.getContext('2d');
        var dataURL;
        canvas.height = this.height;
        canvas.width = this.width;
        ctx.drawImage(this, 0, 0);
        dataURL = canvas.toDataURL('image/jpeg');
        deferred.resolve(dataURL);
    };
    img.src = src;
    return deferred.promise();
}

function makepdf() {
    var pdfContent, a = [], b = [], kontent = [],
        list = $("#tabs ul>li a"),
        imgSources = ['images/weledu.jpg'],
        imgData = {};
    $.getJSON(get_url+'types.php?id='+$('#type').val(), function (newsrc) {
        imgSources.push('images/lamps/'+newsrc.data['0'].image);
        $.each(imgSources, function(index, src) {
            imgData.index = toDataUrl(src);
        });
    });

    $.when.apply(null, imgData).done(function() {
        // pdf creation
    });     
};

如果我在传递给 .done() 的回调中放置一个断点,imgData 对象在那里仍然是空白的!我哪里错了?不是应该完成吗?

这里有一些问题。一是您不能将 $.when.apply 用于对象(字典),只能用于数组。另一个是,当您调用 $.when.apply 时,您的 AJAX 调用尚未完成,因此 imgData 中甚至没有任何数据。

发生的事情是,当您将 empty 对象传递给 $.when.apply 时,它将被视为已解决的承诺(就像您调用 $.when() 没有参数),因此立即调用你的 .done() 方法。这一切都发生在 $.getJSON 完成之前。 (参见 $.when 的文档:https://api.jquery.com/jQuery.when/

还有一点要注意,在 JavaScript 中,对象是 无序的 ,也就是说你不能总是保证每次都以相同的顺序循环它。为了保证顺序,您需要一个数组。

还有一件事要提及,imgData.index = toDataUrl(src); 并不像您想象的那样。这会向您的对象添加一个名为 "index" 的键,它不会使用 index。要执行您期望的操作,请使用 imgData[index] = toDataUrl(src);.

因此,这里的一种解决方案是将 $.when.apply 放在 $.getJSON 并将 imgData 更改为数组。

请注意 $.when 保持 您传递给它的参数的顺序(或者在本例中是您 "applied" 给它的数组)。在 .done() 回调中,您将以正确的顺序传递参数(dataURL 值)。

function makepdf() {
    var pdfContent, a = [], b = [], kontent = [],
        list = $("#tabs ul>li a"),
        imgSources = ['images/weledu.jpg'],
        imgData = [];

    $.getJSON(get_url+'types.php?id='+$('#type').val(), function (newsrc) {
        imgSources.push('images/lamps/'+newsrc.data['0'].image);

        $.each(imgSources, function(index, src) {
            imgData.push(toDataUrl(src));
        });

        // I've always passed `$` as the 1st parameter here, 
        // not sure if it matters
        $.when.apply($, imgData).done(function(img1, img2) {
            // pdf creation
            // Use `img1`, `img2`, etc. here
            // Or loop over `arguments` to get the `dataURL`s
        });     
    });
}