2016-12-08 7 views
0

Мне нужно построить PDF с изображениями. Я думал, что можно предоставить ссылки на локально хранимые файлы, но (пожалуйста, поправьте меня, я был бы так счастлив), оказалось, что PDFmake может работать только с данными: кодированные изображения URI.
Итак, теперь мне нужно преобразовать изображения, НО они должны быть загружены первыми, иначе я ничего не делаю.Словарь отложенных обещаний

Идея в том, что код PDF Здание введено в скобки
$.when.apply(null, imgData).done(function() { });
AFAIK, изображения могут быть загружены в случайном порядке, поэтому для предотвращения баловаться их порядок, я положил их в словарь, где ключ к каждому значению является индекс от intital imgSource массив.
Теперь я впервые использовал Deferred класс и $.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 объект остается пустым там! Где я ошибаюсь? Разве это не должно быть сделано?

+2

'Function.prototype.apply' не применяет объекты, он применяет массивы. – zzzzBov

+0

@zzzzBov отлично, но как я могу быть уверен в том, какой URI этого момента я беру прямо сейчас из результирующего массива?Я с радостью принимаю предложения – mekkanizer

+1

Рассматривая общую проблему, которую вы решаете, вам будет намного лучше загружать изображения и создавать сервер PDF-сервера. Мы делаем это в наших коммерческих приложениях. –

ответ

2

Здесь есть несколько вопросов. Во-первых, вы не можете использовать $.when.apply с объектами (словари), только массивами. Другое дело, что когда вы вызываете $.when.apply, ваш вызов AJAX еще не завершен, поэтому imgData даже не содержит никаких данных.

Что происходит, что когда вы передаете объект пустого к $.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 будет поддерживать порядок параметров, которые вы передаете (или в этом случае массив, который вы «применили» к нему). В обратном вызове .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 
     });  
    }); 
} 
+0

Как насчет загрузки? Это все еще непредсказуемо. Кроме того, у вас не было идеи с ключами: я не собирался * loop * через результирующий dict, я собирался получить доступ к точным элементам, потому что их ключи находятся в том же порядке, что и начальный массив. Я не одержим словарями и с радостью перейду к использованию массива, просто заверите меня, что заказ будет сохранен. – mekkanizer

+0

Что вы подразумеваете под «порядком загрузки»? Вы имеете в виду, что 'toDataUrl()' может заканчивать одно изображение перед другим? –

+0

Да, я имею в виду заказ onload, kinda – mekkanizer