此文仅记录我工作时遇到异步问题的解决办法。
问题一:
在使用dropzone为上传插件时,当设置autoProcessQueue: true就会自动上传,
上传之前会有一个sending函数来处理formData。代码如下
var myDropzone = new Dropzone("#myId", {
paramName: "file",
autoProcessQueue: true,
url: "<c:url value='/uploadFile.htm'><c:param name='methodToCall' value='submitNewDocumentForm2' /></c:url>",
sending: function (file, xhr, formData) {
formData.append("formFile", file);
formData.append("filenames", file.name);
if (file.size > 0) {
EXIF.getData(file,function () {
exifData = JSON.stringify(file.exifdata);
formData.append("exif", exifData);
console.log(exifData)
})
} else {
exifData = "";
}
},
....
}
但是此时我使用的EXIF.getData为一个异步的回调函数,也就是说在还没有执行formData.append("exif", exifData);之前,formData就已经被上传了。所以我现在想让formData.append("exif", exifData);执行后再去执行上传代码。
由于dropzone的上传代码并不能在当前页面显示,所以我要去dropzone.js找到上传代码。ps : 其实只需要找到ajax的send函数就可以了
Dropzone.prototype.submitRequest = function(xhr, formData, files) {
return xhr.send(formData);
};
于是我就顺着找到了submitRequest函数,这个函数就是处理在upload之前发生的所有事件,具体就不看了,主要看在哪里包装了formData
Dropzone.prototype.uploadFiles = function(files) {
var file, formData, handleError, headerName, headerValue, headers, i, input, inputName, inputType, key, method, option, progressObj, response, updateProgress, url, value, xhr, _i, _j, _k, _l, _len, _len1, _len2, _len3, _m, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
....此处省略很多行.....
formData = new FormData();
if (this.options.params) {
_ref1 = this.options.params;
for (key in _ref1) {
value = _ref1[key];
formData.append(key, value);
}
}
for (_j = 0, _len1 = files.length; _j < _len1; _j++) {
file = files[_j];
this.emit("sending", file, xhr, formData);
}
if (this.options.uploadMultiple) {
this.emit("sendingmultiple", files, xhr, formData);
}
if (this.element.tagName === "FORM") {
_ref2 = this.element.querySelectorAll("input, textarea, select, button");
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
input = _ref2[_k];
inputName = input.getAttribute("name");
inputType = input.getAttribute("type");
if (input.tagName === "SELECT" && input.hasAttribute("multiple")) {
_ref3 = input.options;
for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
option = _ref3[_l];
if (option.selected) {
formData.append(inputName, option.value);
}
}
} else if (!inputType || ((_ref4 = inputType.toLowerCase()) !== "checkbox" && _ref4 !== "radio") || input.checked) {
formData.append(inputName, input.value);
}
}
}
for (i = _m = 0, _ref5 = files.length - 1; 0 <= _ref5 ? _m <= _ref5 : _m >= _ref5; i = 0 <= _ref5 ? ++_m : --_m) {
formData.append(this._getParamName(i), files[i], this._renameFilename(files[i].name));
}
return this.submitRequest(xhr, formData, files);
}
所以我们只需要在return this.submitRequest(xhr, formData, files);之前让formData有完整的数据就完美了
所以怎么办呢?
解决办法:
使用promise,具体代码如下:
Dropzone.prototype.uploadFiles = function(files) {
var file, formData, handleError, headerName, headerValue, headers, i, input, inputName, inputType, key, method, option, progressObj, response, updateProgress, url, value, xhr, _i, _j, _k, _l, _len, _len1, _len2, _len3, _m, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
....此处省略很多行.....
var that=this;
var promise=new Promise(function(resolve,reject){
formData = new FormData();
if (that.options.params) {
_ref1 = that.options.params;
for (key in _ref1) {
value = _ref1[key];
formData.append(key, value);
}
}
for (_j = 0, _len1 = files.length; _j < _len1; _j++) {
file = files[_j];
that.emit("sending", file, xhr, formData);
}
if (that.options.uploadMultiple) {
that.emit("sendingmultiple", files, xhr, formData);
}
if (that.element.tagName === "FORM") {
_ref2 = that.element.querySelectorAll("input, textarea, select, button");
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
input = _ref2[_k];
inputName = input.getAttribute("name");
inputType = input.getAttribute("type");
if (input.tagName === "SELECT" && input.hasAttribute("multiple")) {
_ref3 = input.options;
for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
option = _ref3[_l];
if (option.selected) {
formData.append(inputName, option.value);
}
}
} else if (!inputType || ((_ref4 = inputType.toLowerCase()) !== "checkbox" && _ref4 !== "radio") || input.checked) {
formData.append(inputName, input.value);
}
}
}
for (i = _m = 0, _ref5 = files.length - 1; 0 <= _ref5 ? _m <= _ref5 : _m >= _ref5; i = 0 <= _ref5 ? ++_m : --_m) {
formData.append(that._getParamName(i), files[i], that._renameFilename(files[i].name));
}
console.log(formData.get("filenames"));
var timer=setInterval(function(){
if(formData.get("exif")!=null){
clearInterval(timer)
resolve();
}
},100)
});
promise.then(function() {
return that.submitRequest(xhr, formData, files);
},function(error){
console.log(error)
});
};
其实就是把处理formData的代码放入promise中,等他们全部执行完成后,通过if(formData.get("exif")!=null)判断formData.append("exif", exifData);有没有执行,执行完之后才让他上传。
处理中遇到的问题
1.在用promise()包装中的代码,很多都会报出undefined。原因是此时的this会发生变化,所以我凭借以前微信小程序的经验使用var that=this并且把在promise和then里面的this全用that代替。效果果然很好,哈哈哈。







网友评论