Javascript DataTransfer items not persisting through async calls(Javascript DataTransfer 项目不会通过异步调用持久化)
问题描述
我正在使用 Vuejs 和 DataTransfer 异步上传文件,我希望允许一次拖放多个文件进行上传.
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.
我可以进行第一次上传,但在上传完成时,Javascript 已经收集垃圾或更改了 DataTransfer 项目对象.
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.
我怎样才能重做这个(或克隆事件/DataTransfer 对象),以便在整个 ajax 调用过程中我仍然可以使用数据?
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,但我很难将它应用到我的具体案例中.我也尝试过复制事件对象,正如您在我的代码中看到的那样,但它显然不会进行深度复制,只是传递引用,这没有帮助.
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();
}
},
推荐答案
一旦你调用了await
,你就不再在函数的原始调用堆栈中了.这在事件侦听器中尤其重要.
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
重现同样的效果:
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);
})
});
例如拖动四个文件会输出:
For example, dragging four files will output:
DataTransferItemList {0: DataTransferItem, 1: DataTransferItem, 2: DataTransferItem, 3: DataTransferItem, length: 4}
DataTransferItemList {length: 0}
事件发生后,状态发生了变化,物品丢失了.
After the event had happened the state has changed and items have been lost.
有两种方法可以处理这个问题:
There are two ways to handle this issue:
- 复制项目并对其进行迭代
- 将异步作业(Promises)推送到数组中,稍后使用
Promise.all
处理它们
第二种解决方案比在循环中使用 await
更直观.另外,请考虑并行连接受到限制.使用数组,您可以创建块来限制同时上传.
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>
这篇关于Javascript DataTransfer 项目不会通过异步调用持久化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:Javascript DataTransfer 项目不会通过异步调用持久化


- 如何显示带有换行符的文本标签? 2022-01-01
- 为什么悬停在委托事件处理程序中不起作用? 2022-01-01
- 我不能使用 json 使用 react 向我的 web api 发出 Post 请求 2022-01-01
- 如何向 ipc 渲染器发送添加回调 2022-01-01
- 使用 iframe URL 的 jQuery UI 对话框 2022-01-01
- 为什么我的页面无法在 Github 上加载? 2022-01-01
- 如何调试 CSS/Javascript 悬停问题 2022-01-01
- 从原点悬停时触发 translateY() 2022-01-01
- 是否可以将标志传递给 Gulp 以使其以不同的方式 2022-01-01
- 在不使用循环的情况下查找数字数组中的一项 2022-01-01