- 19
- 0
我的需求:
我的需求可以简单描述为,对一个大文件进行分片切割上传。我实现的思路为,
对一个大文件,按照设定的chunksSize切分为N = file.size/chunkSize块,
然后循环创建N个读流读取每个分片的内容,然后发起N个http.request的Post请求去上传文件。
代码如下
(说明: upload函数用来根据分块的个数n,计算每块起始标志位和终止标识位,并调用senddataPromise函数对每片进行操作)
function upload(username,filepath,file_id,filelength,n,alreadychunks,chunkSize) {
return new Promise(function (resolve,reject) {
var start = 0,end = 0;
var promiseall = [];
for (let curindex = 0;curindex < n;curindex++) {
if(filelength - start <= chunkSize) {
end = filelength - 1;
}else {
end = start+chunkSize - 1; // 因读取时包含start和end位
}
if(alreadychunks.indexOf(curindex) == -1) {
let options = {
flags: 'r',
highWaterMark: chunkSize,
start: start,
end: end
};
promiseall.push(senddataPromise(filepath,options,username,file_id,curindex,end-start+1));
}
start = end + 1;
}
let timer = setInterval(() => {
if(promiseall.length == n) {
clearInterval(timer);
Promise.all(promiseall).then(values=>{
console.log(values);
console.log("all done");
resolve(true)
}).catch(err => {
console.log(err);
reject(err);
})
}
},500)
})
}
senddataPromise函数是对第i块分片创建读流读取内容,并调用doapost函数发送到后端
function senddataPromise(path,options,username,summary,curindex,length) {
return new Promise(function (resolve,reject) {
let readSteam = fs.createReadStream(path,options);
readSteam.on("data",(chunk) => {
console.log("第"+curindex+"块 JSON开始")
let chunkjson = JSON.stringify(chunk);
console.log("第"+curindex+"块 JSON结束")
let tempcell = {
data: chunkjson,
n: curindex,
file_id: summary,
username: username,
length: length
};
chunk = null;
chunkjson = null;
doapost(tempcell).then(values=>{
resolve(values)
}).catch(err=>{
reject(err);
});
})
})
}
doapost函数发起post请求发送分片数据
function doapost(data) {
return new Promise(function (resolve,reject) {
let i = data.n;
console.log("第"+i+"份请求准备发出")
let contents = queryString.stringify(data);
data = null;
let options = {
host: "localhost",
path: "/nodepost/",
port: 8000,
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': contents.length
}
};
let req = http.request(options, function (res) {
console.log("第"+i+"份请求返回数据")
res.on("data", function (chunk) {
console.log(chunk.toString());
});
res.on("end", function (d) {
resolve("end");
});
res.on("error", function (e) {
reject(e);
})
});
req.write(contents);
req.end();
contents = null;
console.log("第"+i+"份请求已发出")
})
}
我的问题:
按照正常的思路,因为读取文件内容为异步操作,后面发送请求也为异步操作,所以
也就是说会出现对于n个分片,读取数据已经读取了p片,并且已经有q(**q < p**)片
已经完成上传完成返回数据的情况,但是现在问题是,***发现并没有分片上传完返回数据的
情况出现,都是在n个分片读取完成后,才开始统一执行分片内容上传操作***
图片如下:(由于图片无法上传,我把程序运输出拷贝一下)
{
kind: 'upload',
username: 'moran999',
filepath: 'F:/my_upload_test/NowTest.pdf',
file_id: '-196987878-472217752177633040957425519',
alreadychunks: [],
chunkSize: 1048576,
n: 9 }
第0块 JSON开始
第0块 JSON结束
第0份请求准备发出
第0份请求已发出
第1块 JSON开始
第1块 JSON结束
第1份请求准备发出
第1份请求已发出
第2块 JSON开始
第2块 JSON结束
第2份请求准备发出
第2份请求已发出
第3块 JSON开始
第3块 JSON结束
第3份请求准备发出
第3份请求已发出
第5块 JSON开始
第5块 JSON结束
第5份请求准备发出
第5份请求已发出
第4块 JSON开始
第4块 JSON结束
第4份请求准备发出
第4份请求已发出
第6块 JSON开始
第6块 JSON结束
第6份请求准备发出
第6份请求已发出
第8块 JSON开始
第8块 JSON结束
第8份请求准备发出
第8份请求已发出
第7块 JSON开始
第7块 JSON结束
第7份请求准备发出
第7份请求已发出
第8份请求返回数据
moran999
第4份请求返回数据
moran999
第6份请求返回数据
moran999
第1份请求返回数据
moran999
第2份请求返回数据
moran999
第0份请求返回数据
moran999
第3份请求返回数据
moran999
第7份请求返回数据
moran999
第5份请求返回数据
moran999
[ 'end', 'end', 'end', 'end', 'end', 'end', 'end', 'end', 'end' ]
all done
可以看到其POST数据的发出并不是和读流无关的,即任何一个POST都不会发出,
直到到所有的读流读取完数据,想问一下各位码友是什么原因尼??因为正常
理解下当第i个读流读的时候,前面已经读取完内容的读流完全可以进行post操作
了啊,但实际上并没有。
之所以会问这个问题是因为当我输入的文件比较大时,他执行到《第12块 JSON开始时,
就内存溢出了》,而如果程序是post不用等待所有的读流读完时,当有一部分post执行完之后,其对应的数据就被回收了,释放相应的内存,就不会出现内存溢出了。
0
打赏
收藏
点击回答
- 共 0 条
- 全部回答
-
iii!iii 普通会员 1楼
JavaScript的事件循环是用于处理DOM元素的事件处理程序,以及事件的执行顺序。在JavaScript中,我们通常使用
addEventListener方法为DOM元素添加事件监听器,当事件发生时,事件监听器会调用JavaScript函数来处理事件。但是,事件循环的问题主要有以下几个:
-
事件循环机制:JavaScript的事件循环是一个异步的事件循环机制,这意味着JavaScript会阻塞在事件循环中,等待事件处理程序完成。这样,当用户进行操作,比如点击按钮,JavaScript就会立即执行事件处理程序,但不会等待事件处理程序完成。
-
回调问题:在JavaScript中,事件处理程序通常返回一个函数,这个函数会在事件结束后执行。如果事件处理程序执行了很长时间,或者没有返回函数,那么JavaScript就会一直等待事件处理程序完成,这就会导致页面卡死。
-
事件冒泡问题:在JavaScript中,事件的处理程序会按照事件的冒泡顺序依次执行。这意味着,如果事件在一个元素上触发,那么事件处理程序会首先处理那个元素上的事件,然后处理父元素上的事件,最后处理子元素上的事件。
解决这些问题的方法主要是使用Promise、async/await等异步编程技术,以及使用事件委托和事件循环机制。
-
更多回答
网站公告
- 扫一扫访问手机版
回答动态

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器更新之后。服务器里面有部分玩家要重新创建角色是怎么回事啊?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题函数计算不同地域的是不能用内网吧?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题ARMS可以创建多个应用嘛?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题在ARMS如何申请加入公测呀?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题前端小程序接入这个arms具体是如何接入监控的,这个init方法在哪里进行添加?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器刚到期,是不是就不能再导出存档了呢?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器的游戏版本不兼容 尝试更新怎么解决?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器服务器升级以后 就链接不上了,怎么办?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器转移以后服务器进不去了,怎么解决?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器修改参数后游戏进入不了,是什么情况?预计能赚取 0积分收益
- 回到顶部
- 回到顶部

