【发布时间】:2011-05-12 15:35:08
【问题描述】:
我有一个流程如下:
-
用户执行复杂的搜索,该搜索通过 ajaxly 完成,返回一堆 id(可能是 1,可能是 10000)
-
一旦有了用户,他们就可以选择一些东西,然后下载一个文件(这是一份基于 ID 和他们选择的东西的报告)
为此,我使用了$.download 的高度修改版本
在这里看到:
jQuery.download = function (url, data, method, loadingHolderDivId) {
if (url && typeof data == 'object') {
//for this version, data needs to be a json object.
//loop through the data object..
$('#' + loadingHolderDivId).html($('#LoadingScreen').html());
var theForm = $('<form></form>').attr('action', url).attr('method', method).attr('id', 'jqueryDownloadForm').attr('target', 'iframeX');
$.each(data, function (propertyName, propertyVal) {
if (propertyVal != null) {
if (typeof propertyVal == 'object') {
//HANDLE ARRAYS!
for (var i = 0, len = propertyVal.length; i < len; ++i) {
theForm.append($("<input />").attr('type', 'hidden').attr('id', propertyName + i.toString).attr('name', propertyName).val(propertyVal[i]));
}
}
else {
theForm.append($("<input />").attr('type', 'hidden').attr('id', propertyName).attr('name', propertyName).val(propertyVal));
}
}
});
var iframeX;
var downloadInterval;
// remove old iframe if has
$("#iframeX").remove();
// create new iframe
iframeX = $('<iframe src="javascript:false;" name="iframeX" id="iframeX"></iframe>').appendTo('body').hide();
if ($.browser.msie) {
downloadInterval = setInterval(function () {
// if loading then readyState is “loading” else readyState is “interactive”
if (iframeX && iframeX[0].readyState !== "loading") {
$('#' + loadingHolderDivId).empty();
clearInterval(downloadInterval);
}
}, 23);
}
else {
iframeX.load(function () {
$('#' + loadingHolderDivId).empty();
});
}
theForm.appendTo('body').trigger('submit').remove();
return false;
}
else {
//they didn't fill in the params. do nothing
}
};
基本上,它所做的是解析数据中的内容,并从中构建一个表单。这很好用,当没有很多 id 时。但是当有 8000 时,在 IE 中需要 5 或 10 秒,这并不奇怪,众所周知 IE 不擅长 dom 操作。
另一个问题是,在 IE 中。 $('#' + loadingHolderDivId).html($('#LoadingScreen').html()); 直到完成构建表单之后才会真正发生。我猜这是因为它需要一秒钟才能完成,在它完成之前它已经忙于构建表单了。
我以这种方式构建表单的原因是默认模型绑定器会很高兴并将我的表单绑定到一个可爱的模型中。 id 列表被绑定到 ilist(整数)
以下是控制器操作的示例:
Function ExportUsers(ByVal model As ExportUsersPostModel) As ActionResult
下面是模型的示例:
<Serializable()> _
Public Class ExportUsersPostModel
Public Property FilterUserIds As IList(Of Integer) = New List(Of Integer)
Public Property FilterColumnIds As IList(Of Integer) = New List(Of Integer)
public property ShowThis as boolean
public property OtherStuff as string = string.empty
Public Property FormatId As Integer
End Class
所以实际的问题有两个:
-
如何让我的“加载”消息在它开始以极其缓慢的形式构建死亡之前显示出来?
-
如何加快表单构建,或者以一种不会很慢但仍能让模型绑定器满意的方式构建表单?
【问题讨论】:
-
你为什么要创建一个表单元素而不是使用普通的
$.post()? DOM 操作正在扼杀你的表现。 (您可以使用$.post()让模型绑定器满意) -
不能用ajax获取文件!
-
您可以使用
$.post,将数据存储在服务器上的临时文件中,返回一个密钥,然后使用该密钥导航到下载页面以获取文件。 -
就加速现有代码而言,
$("<input />")比document.createElement("input")慢得多。 JQuery 并不总是解决方案。 -
re:使用 $.post,并不是一个真正的选择。但一个好主意。回复:使用 document.createElement。好电话,没想到。
标签: jquery asp.net-mvc performance internet-explorer download