将 deferred.resolve 从函数内部的操作移动到整个函数完成
Move deferred.resolve from an operation inside a function to the entire function completion
当我在将所有 svg 移动到 canvas 之后将 deferred.resolve 移动到外部时,我没有让整个功能在 deferred.resolve 中工作。我希望 deferred.promise() 在所有 svg 都转换为 canvas 而不仅仅是第一个 svg.
时执行
$(document).ready(function() {
$( '#save_dashboard' ).click(function() {
// Create a deferred object
var dfd = new $.Deferred();
// https://github.com/niklasvh/html2canvas/issues/95#issuecomment-45114424
// First render all SVGs to canvases
targetElem = $('#dashboard');
var elements = targetElem.find('svg').map(function() {
var svg = $(this);
var canvas = $('<canvas></canvas>');
svg.replaceWith(canvas);
// Get the raw SVG string and curate it
var content = svg.wrap('<p></p>').parent().html();
content = content.replace(/xlink:title='hide\/show'/g, '');
content = encodeURIComponent(content);
svg.unwrap();
// Create an image from the svg
var image = new Image();
image.src = 'data:image/svg+xml,' + content;
image.onload = function() {
canvas[0].width = image.width;
canvas[0].height = image.height;
// Render the image to the canvas
var context = canvas[0].getContext('2d');
dfd.resolve(context.drawImage(image, 0, 0));
};
return dfd.promise();
/* return {
svg: svg,
canvas: canvas
}; */
}); // end of targetElem.find('svg').map(function() {...});
// $.when(dfd).done(function(){
// console.log('dfd done');
dfd.then(function(_canvas){
console.log('dfd done', _canvas);
// http://www.kubilayerdogan.net/html2canvas-take-screenshot-of-web-page-and-save-it-to-server-javascript-and-php/
$('#dashboard').html2canvas({
onrendered: function (canvas) {
//Set hidden field's value to image data (base-64 string)
var dashboardPng = canvas.toDataURL('image/png');
console.log('dashboardPng: ' + dashboardPng);
$.ajax({
url:'save_dashboard_image.php',
data:{dashboardPngData: dashboardPng},
type:'POST',
dataType:'json',
success: function(){
console.log('success');
}
,
error: function(xhr, status, error){
console.log('The requested page was: ' + document.URL +
'. The error number returned was: ' + xhr.status +
'. The error message was: ' + error);
}
});
}
});
// }); // end of when(dfd).done()
}); // end of dfd.then(function(_canvas){...})
}); // end of save_dashboard click function
}); // end of document ready
解决方案 修改自以下特里的回答:
$(document).ready(function() {
$( '#save_dashboard' ).click(function() {
// Declare an array to store all deferred objects from each svg element
var svgDfds = [],
targetElem = $('#dashboard');
targetElem.find('svg').each(function() {
var dfd = new $.Deferred(),
svg = $(this),
canvas = $('<canvas></canvas>');
svg.replaceWith(canvas);
// Get the raw SVG string and curate it
var content = svg.wrap('<p></p>').parent().html();
content = content.replace(/xlink:title='hide\/show'/g, '');
content = encodeURIComponent(content);
svg.unwrap();
// Create an image from the svg
var image = new Image();
image.src = 'data:image/svg+xml,' + content;
image.onload = function() {
canvas[0].width = image.width;
canvas[0].height = image.height;
// Render the image to the canvas
var context = canvas[0].getContext('2d');
// Resolve or reject the deferred
dfd.resolve(context.drawImage(image, 0, 0));
};
// Push deferred object into array
svgDfds.push(dfd);
}); // end of targetElem.find('svg').map(function() {...});
// Check for all deferreds
$.when.apply($, svgDfds).then(function(_canvas) {
console.log('dfd done', _canvas);
// http://www.kubilayerdogan.net/html2canvas-take-screenshot-of-web-page-and-save-it-to-server-javascript-and-php/
$('#dashboard').html2canvas({
onrendered: function (canvas) {
//Set hidden field's value to image data (base-64 string)
var dashboardPng = canvas.toDataURL('image/png');
console.log('dashboardPng: ' + dashboardPng);
$.ajax({
url:'save_dashboard_image.php',
data:{dashboardPngData: dashboardPng},
type:'POST',
dataType:'json',
success: function(){
console.log('success');
}
,
error: function(xhr, status, error){
console.log('The requested page was: ' + document.URL +
'. The error number returned was: ' + xhr.status +
'. The error message was: ' + error);
}
});
}
});
});
}); // end of save_dashboard click function
}); // end of document ready
您不能对多个图像加载使用单个延迟。每个图像都需要自己的 deferred,这样你就可以为它创建一个专用的 promise。只有这样你才能得到一系列不同的承诺(每个承诺在加载各自的图像时解决),然后你可以 pass all to $.when
等待它们。
您的代码应如下所示:
$( '#save_dashboard' ).click(function() {
var targetElem = $('#dashboard');
var elementPromises = targetElem.find('svg').map(function() {
// Create the deferred objects here!
var dfd = new $.Deferred();
…
var image = new Image();
…
image.onload = function() {
…
dfd.resolve(context.drawImage(image, 0, 0));
};
return dfd.promise();
}).get(); // an array, not a jquery collection
var allLoaded = $.when.apply($, elementPromises);
allLoaded.then(…);
});
您应该按以下方式构建代码:
- 在点击时创建一个新数组,用它来存储所有来自 SVG 的延迟
- 遍历所有 SVG 元素
- 在每个实例中,创建一个新的内部延迟对象
- 解决或拒绝延期
- 将其推入循环外的数组
- 使用
$.when.apply($, arrayOfDeferredObjects)
检查数组中所有延迟对象的状态
在代码中,应该如下所示:
$('#save_dashboard').click(function() {
var svgDfd = [], // Declare an array to store ALL deferreds from svgs
$targetElem = $('#dashboard');
// Use .each() to iterate through all SVGs
$targetElem.find('svg').each(function() {
// New deferred object per SVG instance
var dfd = new $.Deferred();
// At some point in your code, resolve or reject the deferred
dfd.resolve();
// Push deferred object into array
svgDfds.push(dfd);
}
// Check for all deferreds
$.when.apply($, svgDfds).then(function() {
// Do stuff
});
});
因此,对您的代码稍作修改和重构以适应上述范例:
$(document).ready(function() {
$( '#save_dashboard' ).click(function() {
// Declare an array to store all deferredo objects from each svg element
var svgDfds = [],
$targetElem = $('#dashboard');
$targetElem.find('svg').each(function() {
var dfd = new $.Deferred(),
svg = $(this),
canvas = $('<canvas></canvas>');
svg.replaceWith(canvas);
// Get the raw SVG string and curate it
var content = svg.wrap('<p></p>').parent().html();
content = content.replace(/xlink:title='hide\/show'/g, '');
content = encodeURIComponent(content);
svg.unwrap();
// Create an image from the svg
var image = new Image();
image.src = 'data:image/svg+xml,' + content;
image.onload = function() {
canvas[0].width = image.width;
canvas[0].height = image.height;
// Render the image to the canvas
var context = canvas[0].getContext('2d');
dfd.resolve(context.drawImage(image, 0, 0));
};
svgDfds.push(dfd);
});
$.when.apply($, svgDfds).then(function(){
$('#dashboard').html2canvas({
onrendered: function (canvas) {
//Set hidden field's value to image data (base-64 string)
var dashboardPng = canvas.toDataURL('image/png');
console.log('dashboardPng: ' + dashboardPng);
$.ajax({
url:'save_dashboard_image.php',
data:{dashboardPngData: dashboardPng},
type:'POST',
dataType:'json',
success: function(){
console.log('success');
}
,
error: function(xhr, status, error){
console.log('The requested page was: ' + document.URL +
'. The error number returned was: ' + xhr.status +
'. The error message was: ' + error);
}
});
}
});
});
});
});
当我在将所有 svg 移动到 canvas 之后将 deferred.resolve 移动到外部时,我没有让整个功能在 deferred.resolve 中工作。我希望 deferred.promise() 在所有 svg 都转换为 canvas 而不仅仅是第一个 svg.
时执行$(document).ready(function() {
$( '#save_dashboard' ).click(function() {
// Create a deferred object
var dfd = new $.Deferred();
// https://github.com/niklasvh/html2canvas/issues/95#issuecomment-45114424
// First render all SVGs to canvases
targetElem = $('#dashboard');
var elements = targetElem.find('svg').map(function() {
var svg = $(this);
var canvas = $('<canvas></canvas>');
svg.replaceWith(canvas);
// Get the raw SVG string and curate it
var content = svg.wrap('<p></p>').parent().html();
content = content.replace(/xlink:title='hide\/show'/g, '');
content = encodeURIComponent(content);
svg.unwrap();
// Create an image from the svg
var image = new Image();
image.src = 'data:image/svg+xml,' + content;
image.onload = function() {
canvas[0].width = image.width;
canvas[0].height = image.height;
// Render the image to the canvas
var context = canvas[0].getContext('2d');
dfd.resolve(context.drawImage(image, 0, 0));
};
return dfd.promise();
/* return {
svg: svg,
canvas: canvas
}; */
}); // end of targetElem.find('svg').map(function() {...});
// $.when(dfd).done(function(){
// console.log('dfd done');
dfd.then(function(_canvas){
console.log('dfd done', _canvas);
// http://www.kubilayerdogan.net/html2canvas-take-screenshot-of-web-page-and-save-it-to-server-javascript-and-php/
$('#dashboard').html2canvas({
onrendered: function (canvas) {
//Set hidden field's value to image data (base-64 string)
var dashboardPng = canvas.toDataURL('image/png');
console.log('dashboardPng: ' + dashboardPng);
$.ajax({
url:'save_dashboard_image.php',
data:{dashboardPngData: dashboardPng},
type:'POST',
dataType:'json',
success: function(){
console.log('success');
}
,
error: function(xhr, status, error){
console.log('The requested page was: ' + document.URL +
'. The error number returned was: ' + xhr.status +
'. The error message was: ' + error);
}
});
}
});
// }); // end of when(dfd).done()
}); // end of dfd.then(function(_canvas){...})
}); // end of save_dashboard click function
}); // end of document ready
解决方案 修改自以下特里的回答:
$(document).ready(function() {
$( '#save_dashboard' ).click(function() {
// Declare an array to store all deferred objects from each svg element
var svgDfds = [],
targetElem = $('#dashboard');
targetElem.find('svg').each(function() {
var dfd = new $.Deferred(),
svg = $(this),
canvas = $('<canvas></canvas>');
svg.replaceWith(canvas);
// Get the raw SVG string and curate it
var content = svg.wrap('<p></p>').parent().html();
content = content.replace(/xlink:title='hide\/show'/g, '');
content = encodeURIComponent(content);
svg.unwrap();
// Create an image from the svg
var image = new Image();
image.src = 'data:image/svg+xml,' + content;
image.onload = function() {
canvas[0].width = image.width;
canvas[0].height = image.height;
// Render the image to the canvas
var context = canvas[0].getContext('2d');
// Resolve or reject the deferred
dfd.resolve(context.drawImage(image, 0, 0));
};
// Push deferred object into array
svgDfds.push(dfd);
}); // end of targetElem.find('svg').map(function() {...});
// Check for all deferreds
$.when.apply($, svgDfds).then(function(_canvas) {
console.log('dfd done', _canvas);
// http://www.kubilayerdogan.net/html2canvas-take-screenshot-of-web-page-and-save-it-to-server-javascript-and-php/
$('#dashboard').html2canvas({
onrendered: function (canvas) {
//Set hidden field's value to image data (base-64 string)
var dashboardPng = canvas.toDataURL('image/png');
console.log('dashboardPng: ' + dashboardPng);
$.ajax({
url:'save_dashboard_image.php',
data:{dashboardPngData: dashboardPng},
type:'POST',
dataType:'json',
success: function(){
console.log('success');
}
,
error: function(xhr, status, error){
console.log('The requested page was: ' + document.URL +
'. The error number returned was: ' + xhr.status +
'. The error message was: ' + error);
}
});
}
});
});
}); // end of save_dashboard click function
}); // end of document ready
您不能对多个图像加载使用单个延迟。每个图像都需要自己的 deferred,这样你就可以为它创建一个专用的 promise。只有这样你才能得到一系列不同的承诺(每个承诺在加载各自的图像时解决),然后你可以 pass all to $.when
等待它们。
您的代码应如下所示:
$( '#save_dashboard' ).click(function() {
var targetElem = $('#dashboard');
var elementPromises = targetElem.find('svg').map(function() {
// Create the deferred objects here!
var dfd = new $.Deferred();
…
var image = new Image();
…
image.onload = function() {
…
dfd.resolve(context.drawImage(image, 0, 0));
};
return dfd.promise();
}).get(); // an array, not a jquery collection
var allLoaded = $.when.apply($, elementPromises);
allLoaded.then(…);
});
您应该按以下方式构建代码:
- 在点击时创建一个新数组,用它来存储所有来自 SVG 的延迟
- 遍历所有 SVG 元素
- 在每个实例中,创建一个新的内部延迟对象
- 解决或拒绝延期
- 将其推入循环外的数组
- 使用
$.when.apply($, arrayOfDeferredObjects)
检查数组中所有延迟对象的状态
在代码中,应该如下所示:
$('#save_dashboard').click(function() {
var svgDfd = [], // Declare an array to store ALL deferreds from svgs
$targetElem = $('#dashboard');
// Use .each() to iterate through all SVGs
$targetElem.find('svg').each(function() {
// New deferred object per SVG instance
var dfd = new $.Deferred();
// At some point in your code, resolve or reject the deferred
dfd.resolve();
// Push deferred object into array
svgDfds.push(dfd);
}
// Check for all deferreds
$.when.apply($, svgDfds).then(function() {
// Do stuff
});
});
因此,对您的代码稍作修改和重构以适应上述范例:
$(document).ready(function() {
$( '#save_dashboard' ).click(function() {
// Declare an array to store all deferredo objects from each svg element
var svgDfds = [],
$targetElem = $('#dashboard');
$targetElem.find('svg').each(function() {
var dfd = new $.Deferred(),
svg = $(this),
canvas = $('<canvas></canvas>');
svg.replaceWith(canvas);
// Get the raw SVG string and curate it
var content = svg.wrap('<p></p>').parent().html();
content = content.replace(/xlink:title='hide\/show'/g, '');
content = encodeURIComponent(content);
svg.unwrap();
// Create an image from the svg
var image = new Image();
image.src = 'data:image/svg+xml,' + content;
image.onload = function() {
canvas[0].width = image.width;
canvas[0].height = image.height;
// Render the image to the canvas
var context = canvas[0].getContext('2d');
dfd.resolve(context.drawImage(image, 0, 0));
};
svgDfds.push(dfd);
});
$.when.apply($, svgDfds).then(function(){
$('#dashboard').html2canvas({
onrendered: function (canvas) {
//Set hidden field's value to image data (base-64 string)
var dashboardPng = canvas.toDataURL('image/png');
console.log('dashboardPng: ' + dashboardPng);
$.ajax({
url:'save_dashboard_image.php',
data:{dashboardPngData: dashboardPng},
type:'POST',
dataType:'json',
success: function(){
console.log('success');
}
,
error: function(xhr, status, error){
console.log('The requested page was: ' + document.URL +
'. The error number returned was: ' + xhr.status +
'. The error message was: ' + error);
}
});
}
});
});
});
});