Javascript 承诺期间(fs readstream)
我为自动上传备份文件(在Backblaze上)制作了一个脚本 制作一个脚本,将完整文件加载到Javascript 承诺期间(fs readstream),javascript,node.js,promise,async-await,fs,Javascript,Node.js,Promise,Async Await,Fs,我为自动上传备份文件(在Backblaze上)制作了一个脚本 制作一个脚本,将完整文件加载到常量中,当文件大小增加(从1 GB增加到3gb以上)时,拆分字符串并上载每个部分。我的脚本崩溃 我试图完全异步地重写脚本 我这样写: 异步getFileInfoAndUploadPart(路径,sizeChunk=1024){ 常数信息={ sha1:null, 尺寸:0, 零件号:0, 第1部分:{}, }; 返回新承诺(解决=>{ const shasumGlobal=crypto.createHas
常量中,当文件大小增加(从1 GB增加到3gb以上)时,拆分字符串并上载每个部分。我的脚本崩溃
我试图完全异步地重写脚本
我这样写:
异步getFileInfoAndUploadPart(路径,sizeChunk=1024){
常数信息={
sha1:null,
尺寸:0,
零件号:0,
第1部分:{},
};
返回新承诺(解决=>{
const shasumGlobal=crypto.createHash('sha1');
日志(路径,sizeChunk);
常量输入=fs.createReadStream(路径);
input.on('readable',()=>{
console.log('1');
让块;
while((chunk=input.read(sizeChunk))!==null){
console.log('2');
const tempShasum=crypto.createHash('sha1');
shasumGlobal.update(chunk);
tempShasum.update(块);
info.partNumber+=1;
info.partSha1[info.partNumber]=tempShasum.digest('hex');
}
console.log('3');
info.sha1=shasumGlobal.digest('hex');
解决(信息);
});
});
}
但承诺在之前解决,而:/
什么是正确的方法,使这同时完成之前,我的承诺
(在上传每个部件时,我需要在此过程中调用异步函数)
编辑
最后,我使用了以下方法:
异步getFileInfoAndUploadPart(路径,sizeChunk=1024,文件ID='xxx'){
返回新承诺(解决=>{
常数信息={
fileId:fileId,
sha1:null,
尺寸:0,
零件号:0,
第1部分:{},
};
const input=fs.createReadStream(路径{highWaterMark:sizeChunk});
const shasumGlobal=crypto.createHash('sha1');
input.on('data',异步数据块=>{
const shasumPart=await crypto.createHash('sha1');
等待shasumPart.update(数据块);
等待shasumGlobal.update(dataChunk);
info.partNumber+=1;
info.partSha1[info.partNumber]=shasumPart.digest('hex');
});
input.on('end',()=>{
info.sha1=shasumGlobal.digest('hex');
解决(信息);
});
});
}
编辑2:
上面的代码工作不好
首先,您需要在播放数据时暂停流,并在可以处理下一部分时恢复流
第二个错误:
如果你用10个10月的文件来尝试这段代码,并使用5个10月的区块
第一次触发“数据”事件=>ok
第二次触发“数据”事件=>ok
触发“结束”事件=>ok
但是如果您想将流分成3部分(Math.ceil(fileSize/chunkSize)=>4+4+2,则只需将最后一部分缩短)
第一次触发“数据”事件=>ok
第二次触发“数据”事件=>ok
您第三次触发“数据”事件,但是
您到达流的末尾,因此在
同时
只有在“数据”逻辑完成后,我才找到触发“结束”事件的任何解决方案
因此,我认为我预先计算了区块的数量,并在“数据”事件中实现了我的“结束”逻辑,当我在最后一个区块上时…async getFileInfoAndUploadPart(path,sizeChunk=1024,fileId='xxx'){
返回新承诺(解决=>{
const stats=fs.statSync(路径);
常数信息={
fileId:fileId,
sha1:null,
尺寸:0,
零件号:0,
零件号理论:Math.ceil(统计数据、尺寸/尺寸),
第1部分:{},
};
const input=fs.createReadStream(路径{highWaterMark:sizeChunk});
const shasumGlobal=crypto.createHash('sha1');
input.on('data',异步数据块=>{
input.pause();
const shasumPart=crypto.createHash('sha1');
shasumPart.update(数据块);
shasumGlobal.update(dataChunk);
info.partNumber+=1;
info.partSha1[info.partNumber]=shasumPart.digest('hex');
//强制传递信息对象的副本。
//等待这个.uploadWithRetry(dataChunk,{…info},parameters.getConfig('maxRetry'),parameters.getConfig('waitbeforetry'));
等待这个。debug()。然后(()=>{
log({…info});
});
input.resume();
if(信息零件号===信息零件号理论){
console.log('end');
info.sha1=shasumGlobal.digest('hex');
解决(信息);
}
});
});
}
PS:调试是这个函数的一部分
异步调试(时间=1000){
返回新承诺(解决=>{
设置超时(()=>{
解决();
},时间);
});
};
while循环结束之前,您的承诺不会得到解决。可能存在这样一种情况:promise回调中的代码失败,因此promise可能会拒绝,而不是解决。尝试将.catch(err=>console.log(err))
添加到getFileInfoAndUploadPart
函数返回的结果中,并检查脚本崩溃是什么错误,因为我调用了shasumGlobal.update(chunk)代码>在shasumGlobal.digest('hex')之后代码>(在我的控制台中,我看到了<代码> 1代码/代码>,代码> 3 <代码>,然后返回我的函数……然后崩溃……(从来没有看到<代码> 2代码/代码……)我们用节点中的异步迭代器直接支持迭代流,考虑使用<代码>等待< /代码>