問題描述
我正在使用 Vuejs 和 DataTransfer 異步上傳文件,我希望允許一次拖放多個(gè)文件進(jìn)行上傳.
I am using Vuejs along with DataTransfer to upload files asynchronously, and I want to allow multiple files to be dragged and dropped for upload at once.
我可以進(jìn)行第一次上傳,但在上傳完成時(shí),Javascript 已經(jīng)收集垃圾或更改了 DataTransfer 項(xiàng)目對(duì)象.
I can get the first upload to happen, but by the time that upload is done, Javascript has either garbage collected or changed the DataTransfer items object.
我怎樣才能重做這個(gè)(或克隆事件/DataTransfer 對(duì)象),以便在整個(gè) ajax 調(diào)用過程中我仍然可以使用數(shù)據(jù)?
How can I rework this (or clone the event/DataTransfer object) so that the data is still available to me throughout the ajax calls?
我已按照 MDN 文檔了解如何使用 DataTransfer,但我很難將它應(yīng)用到我的具體案例中.我也嘗試過復(fù)制事件對(duì)象,正如您在我的代碼中看到的那樣,但它顯然不會(huì)進(jìn)行深度復(fù)制,只是傳遞引用,這沒有幫助.
I've followed the MDN docs on how to use DataTransfer but I'm having a hard time applying it to my specific case. I also have tried copying the event objects, as you can see in my code, but it obviously does not do a deep copy, just passes the reference, which doesn't help.
methods: {
dropHandler: function (event) {
if (event.dataTransfer.items) {
let i = 0;
let self = this;
let ev = event;
function uploadHandler() {
let items = ev.dataTransfer.items;
let len = items.length;
// len NOW EQUALS 4
console.log("LEN: ", len);
if (items[i].kind === 'file') {
var file = items[i].getAsFile();
$('#id_file_name').val(file.name);
var file_form = $('#fileform2').get(0);
var form_data = new FormData(file_form);
if (form_data) {
form_data.append('file', file);
form_data.append('type', self.type);
}
$('#file_progress_' + self.type).show();
var post_url = '/blah/blah/add/' + self.object_id + '/';
$.ajax({
url: post_url,
type: 'POST',
data: form_data,
contentType: false,
processData: false,
xhr: function () {
var xhr = $.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener('progress', function (event) {
var percent = 0;
var position = event.loaded || event.position;
var total = event.total;
if (event.lengthComputable) {
percent = Math.ceil(position / total * 100);
$('#file_progress_' + self.type).val(percent);
}
}, true);
}
return xhr;
}
}).done((response) => {
i++;
if (i < len) {
// BY NOW, LEN = 0. ????
uploadHandler();
} else {
self.populate_file_lists();
}
}
);
}
}
uploadHandler();
}
},
推薦答案
一旦你調(diào)用了await
,你就不再在函數(shù)的原始調(diào)用堆棧中了.這在事件偵聽器中尤其重要.
Once you call await
you're no longer in the original call stack of the function. This is something that would matter particularly in the event listener.
我們可以用setTimeout
重現(xiàn)同樣的效果:
We can reproduce the same effect with setTimeout
:
dropZone.addEventListener('drop', async (e) => {
e.preventDefault();
console.log(e.dataTransfer.items);
setTimeout(()=> {
console.log(e.dataTransfer.items);
})
});
例如拖動(dòng)四個(gè)文件會(huì)輸出:
For example, dragging four files will output:
DataTransferItemList?{0: DataTransferItem, 1: DataTransferItem, 2: DataTransferItem, 3: DataTransferItem, length: 4}
DataTransferItemList?{length: 0}
事件發(fā)生后,狀態(tài)發(fā)生了變化,物品丟失了.
After the event had happened the state has changed and items have been lost.
有兩種方法可以處理這個(gè)問題:
There are two ways to handle this issue:
- 復(fù)制項(xiàng)目并對(duì)其進(jìn)行迭代
- 將異步作業(yè)(Promises)推送到數(shù)組中,稍后使用
Promise.all
處理它們
第二種解決方案比在循環(huán)中使用 await
更直觀.另外,請(qǐng)考慮并行連接受到限制.使用數(shù)組,您可以創(chuàng)建塊來(lái)限制同時(shí)上傳.
The second solution is more intuitive than using await
in the loop. Also, consider parallel connections are limited. With an array you can create chunks to limit simultaneous uploads.
function pointlessDelay() {
return new Promise((resolve, reject) => {
setTimeout(resolve, 1000);
});
}
const dropZone = document.querySelector('.dropZone');
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
});
dropZone.addEventListener('drop', async (e) => {
e.preventDefault();
console.log(e.dataTransfer.items);
const queue = [];
for (const item of e.dataTransfer.items) {
console.log('next loop');
const entry = item.webkitGetAsEntry();
console.log({item, entry});
queue.push(pointlessDelay().then(x=> console.log(`${entry.name} uploaded`)));
}
await Promise.all(queue);
});
body {
font-family: sans-serif;
}
.dropZone {
display: inline-flex;
background: #3498db;
color: #ecf0f1;
border: 0.3em dashed #ecf0f1;
border-radius: 0.3em;
padding: 5em;
font-size: 1.2em;
}
<div class="dropZone">
Drop Zone
</div>
這篇關(guān)于Javascript DataTransfer 項(xiàng)目不會(huì)通過異步調(diào)用持久化的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!