javascript - 异步循环似乎部分并行
问题描述
我正在尝试实现一个函数,它将文件切成块,然后将它们一个接一个地发送到我的后端。
该函数必须在开始上传之前对每个文件进行哈希处理并验证哈希是否已知。以下代码是代码部分,其中调用了我的有问题的函数。
process: async (
fieldName,
file,
metadata,
load,
error,
progress,
abort,
transfer,
options,
) => {
// fieldName is the name of the input field - No direct relevance for us
// logger.log(`fieldName: ${fieldName}`);
// Usually Empty - Can be added with Metadata-Plugin
// logger.log(metadata);
const source = this.$axios.CancelToken.source();
const abortProcess = () => {
// This function is entered if the user has tapped the cancel button
source.cancel('Operation cancelled by user');
// Let FilePond know the request has been cancelled
abort();
};
let chunks = [];
const {
chunkForce,
chunkRetryDelays,
chunkServer,
chunkSize,
chunkTransferId,
chunkUploads,
} = options;
// Needed Parameters of file
const { name, size } = file;
if (chunkTransferId) {
/** Here we handle what happens, when Retry-Button is pressed */
logger.log(`Already defined: ${chunkTransferId}`);
return { abortProcess };
}
this.hashFile(file)
.then((hash) => {
logger.log(`File Hashed: ${hash}`);
if (hash.length === 0) {
error('Hash not computable');
}
return hash;
})
.then((hash) => {
logger.log(`Hash passed through: ${hash}`);
return this.requestTransferId(file, hash, source.token)
.then((transferId) => {
logger.log(`T-ID receieved: ${transferId}`);
return transferId;
})
.catch((err) => {
error(err);
});
})
.then((transferId) => {
transfer(transferId);
logger.log(`T-ID passed through: ${transferId}`);
// Split File into Chunks to prepare Upload
chunks = this.splitIntoChunks(file, chunkSize);
// Filter Chunks - Remove all those which have already been uploaded with success
const filteredChunks = chunks.filter(
(chunk) => chunk.status !== ChunkStatus.COMPLETE,
);
logger.log(filteredChunks);
return this.uploadChunks(
filteredChunks,
{ name, size, transferId },
progress,
error,
source.token,
).then(() => transferId);
})
.then((transferId) => {
// Now Everything should be uploaded -> Set Progress to 100% and make item appear finished
progress(true, size, size);
load(transferId);
logger.log(transferId);
})
.catch((err) => error(err));
return { abortProcess };
},
uploadChunks
是问题开始的地方。
async uploadChunks(chunks, options, progress, error, cancelToken) {
const { name, size, transferId } = options;
for (let index = 0; index < chunks.length; index += 1) {
let offset = 0;
const chunk = chunks[index];
chunk.status = ChunkStatus.PROCESSING;
// eslint-disable-next-line no-await-in-loop
await this.uploadChunk(chunk.chunk, options, offset)
.then(() => {
chunk.status = ChunkStatus.COMPLETE;
offset += chunk.chunk.size;
progress(true, offset, size);
logger.log(offset); // This is always chunk.chunk.size, instead of getting bigger
})
.catch((err) => {
chunk.status = ChunkStatus.ERROR;
error(err);
});
}
},
uploadChunk(fileChunk, options, offset) {
const { name, size, transferId } = options;
const apiURL = `${this.$config.api_url}/filepond/patch?id=${transferId}`;
return this.$axios.$patch(apiURL, fileChunk, {
headers: {
'content-type': 'application/offset+octet-stream',
'upload-name': name,
'upload-length': size,
'upload-offset': offset,
},
});
},
如您所见uploadChunks
,需要一组块、一些选项、两个函数(进度和错误)和一个 cancelToken(我目前不使用,因为我仍然遇到这个问题)
数组中的每个块具有以下形式:
{
status: 0, // Some Status indicating, if it's completed or not
chunk: // binary data
}
该函数uploadChunks
迭代块数组,理论上应该一个接一个地上传一个块,并且offset
每次上传后总是递增,然后调用progress
. 在此之后,它应该开始循环的下一次迭代,其中offset
将比之前的调用更大。
调用本身一个接一个地执行,但每个调用都相同offset
,progress
不会被重复调用。相反100%
,由于load
最后第一个函数中的 -call,我的进度条会锁定,直到所有内容都上传并且它们跳转到 。
因此,上传本身以正确的顺序正常工作,但是await this.uploadChunk...
在每个块之后都不会调用所有代码并以某种方式阻塞。
解决方案
您offset
在循环内设置为 0 。所以偏移量总是0。你应该移动这条线:
let offset = 0;
在for
声明之前。
推荐阅读
- python - 使用参数运行 jupyter nbextensions
- node.js - 如何在 JOI 验证中自定义消息
- git - Git如何撤消最近的合并提交然后更改为变基
- php - 如何对所有元素值求和并将该数字附加到数组的末尾?
- angular-material - 如何从角度材料转换日期格式
- java - 移动迭代器语句使代码编译
- javascript - 如何在这个 Chrome 扩展代码中有多个指令?
- prolog - 从列表 Prolog 中挑选元素
- swift - 为什么 serviceSubscriberCellularProviders 返回 nil?(在 iOS 12 中)
- python-3.x - TypeError:需要一个整数(得到类型 str)?