我正在构建一个使用EvaporateJS的Web应用程序,使用Multipart上传将大文件上传到Amazon S3.我注意到一个问题,每次启动新块时,浏览器都会冻结约2秒钟.我希望用户能够在上传过程中继续使用我的应用程序,这种冻结会让人感觉很糟糕.
我使用Chrome的时间轴来查看造成这种情况的原因,发现它是SparkMD5的散列.所以我把整个上传过程转移到了一个工作者,我认为这会解决问题.
那么问题现在已经在Edge和Firefox中得到修复,但Chrome仍然存在完全相同的问题.
这是我的时间轴的截图:
正如你所看到的,在冻结期间,我的主线程基本上什么也没做,在此期间运行<8ms的JavaScript.所有工作都在我的工作线程中进行,即使只运行约600ms左右,而不是我的框架所需的1386ms.
我真的不确定是什么导致了这个问题,是否有任何与工人有关的问题我应该注意什么?
这是我的工人的代码:
var window = self; // For Worker-unaware scripts // Shim to make Evaporate work in a Worker var document = { createElement: function() { var href = undefined; var elm = { set href(url) { var obj = new URL(url); elm.protocol = obj.protocol; elm.hostname = obj.hostname; elm.pathname = obj.pathname; elm.port = obj.port; elm.search = obj.search; elm.hash = obj.hash; elm.host = obj.host; href = url; }, get href() { return href; }, protocol: undefined, hostname: undefined, pathname: undefined, port: undefined, search: undefined, hash: undefined, host: undefined }; return elm; } }; importScripts("/lib/sha256/sha256.min.js"); importScripts("/lib/spark-md5/spark-md5.min.js"); importScripts("/lib/url-parse/url-parse.js"); importScripts("/lib/xmldom/xmldom.js"); importScripts("/lib/evaporate/evaporate.js"); DOMParser = self.xmldom.DOMParser; var defaultConfig = { computeContentMd5: true, cryptoMd5Method: function (data) { return btoa(SparkMD5.ArrayBuffer.hash(data, true)); }, cryptoHexEncodedHash256: sha256, awsSignatureVersion: "4", awsRegion: undefined, aws_url: "https://s3-ap-southeast-2.amazonaws.com", aws_key: undefined, customAuthMethod: function(signParams, signHeaders, stringToSign, timestamp, awsRequest) { return new Promise(function(resolve, reject) { var signingRequestId = currentSigningRequestId++; postMessage(["signingRequest", signingRequestId, signParams.videoId, timestamp, awsRequest.signer.canonicalRequest()]); queuedSigningRequests[signingRequestId] = function(signature) { queuedSigningRequests[signingRequestId] = undefined; if(signature) { resolve(signature); } else { reject(); } } }); }, //logging: false, bucket: undefined, allowS3ExistenceOptimization: false, maxConcurrentParts: 5 } var currentSigningRequestId = 0; var queuedSigningRequests = []; var e = undefined; var filekey = undefined; onmessage = function(e) { var messageType = e.data[0]; switch(messageType) { case "init": var globalConfig = {}; for(var k in defaultConfig) { globalConfig[k] = defaultConfig[k]; } for(var k in e.data[1]) { globalConfig[k] = e.data[1][k]; } var uploadConfig = e.data[2]; Evaporate.create(globalConfig).then(function(evaporate) { var e = evaporate; filekey = globalConfig.bucket + "/" + uploadConfig.name; uploadConfig.progress = function(p, stats) { postMessage(["progress", p, stats]); }; uploadConfig.complete = function(xhr, awsObjectKey, stats) { postMessage(["complete", xhr, awsObjectKey, stats]); } uploadConfig.info = function(msg) { postMessage(["info", msg]); } uploadConfig.warn = function(msg) { postMessage(["warn", msg]); } uploadConfig.error = function(msg) { postMessage(["error", msg]); } e.add(uploadConfig); }); break; case "pause": e.pause(filekey); break; case "resume": e.resume(filekey); break; case "cancel": e.cancel(filekey); break; case "signature": var signingRequestId = e.data[1]; var signature = e.data[2]; queuedSigningRequests[signingRequestId](signature); break; } }
请注意,它依赖于调用线程为其提供AWS公钥,AWS Bucket Name和AWS区域,AWS Object Key和输入File对象,这些都在"init"消息中提供.当需要签名时,它会向父线程发送'signingRequest'消息,一旦从我的API签名端点获取签名,就会在签名中提供签名.