从Javascript, spliced FileReader for large files with Promises, how?演变,它向我展示了Promise如何解析函数,现在我仍然坚持使用相同但在Array.reduce函数内部。
目标是我想在一个数组中上传一个文件(已经存在),其中每个数组项(文件)按顺序上传(即通过promises控制)。
然后,我理解答案是http://www.html5rocks.com/en/tutorials/es6/promises/?redirect_from_locale=es中的某种方式,但我无法理解如何将其应用于此处。我的数组不是promises数组,是一个文件数组。好吧,整件事情仍然让我感到困惑。
这是我的代码,如果我能看到ein
console.log消息,它会起作用:
return myArray.reduce(function(previous, current) {
var BYTES_PER_CHUNK = 100000;
var start = 0;
var temp_end = start + BYTES_PER_CHUNK;
var end = parseInt(current.size);
if (temp_end > end) temp_end = end;
var content = ''; // to be filled by the content of the file
var uploading_file = current;
Promise.resolve().then(function() {
return upload();
})
.then(function(content){
// do stuff with the content
Promise.resolve();
});
},0) // I add the 0 in case myArray has only 1 item
//},Promise.resolve()) goes here?
.then(function(){
console.log('ein') // this I never see
});
function upload() {
if (start < end) {
return new Promise(function(resolve){
var chunk = uploading_file.slice(start, temp_end);
var reader = new FileReader();
reader.readAsArrayBuffer(chunk);
reader.onload = function(e) {
if (e.target.readyState == 2) {
content += new TextDecoder("utf-8").decode(e.target.result);
start = temp_end;
temp_end = start + BYTES_PER_CHUNK;
if (temp_end > end) temp_end = end;
resolve(upload());
}
}
});
} else {
uploading_file = null;
return Promise.resolve(content);
}
}
经过多次评论后更新,似乎现在可行了......还不确定
var uploaded_file,start,temp_end,end,content; var BYTES_PER_CHUNK = 100000;
myArray.reduce(function(previous,current){ 返回上一个 .then(function(){ BYTES_PER_CHUNK = 100000; start = 0; temp_end = start + BYTES_PER_CHUNK; end = parseInt(current.size); if(temp_end&gt; end)temp_end = end; content =''; uploaded_file = current;
upload()
.then(function(content){
// do stuff with "content"
console.log('here')
return Promise.resolve();
});
}); },Promise.resolve()) 。然后(函数(){ 的console.log( 'EIN'); });
function upload(){ if(start&lt; end){ 返回新的Promise(function(resolve){ var chunk = uploaded_file.slice(start,temp_end); var reader = new FileReader(); reader.readAsArrayBuffer(块); reader.onload = function(e){ if(e.target.readyState == 2){ content + = new TextDecoder(“utf-8”)。decode(e.target.result); start = temp_end; temp_end = start + BYTES_PER_CHUNK; if(temp_end&gt; end)temp_end = end; 决心(上传()); } } }); } else { uploaded_file = null; return Promise.resolve(content); } }
改进代码,似乎有用,也许更容易阅读?
var start, temp_end, end;
var BYTES_PER_CHUNK = 100000;
myArray.reduce(function(previous, current) {
return previous
.then(function() {
start = 0;
temp_end = start + BYTES_PER_CHUNK;
end = parseInt(current.size);
if (temp_end > end) temp_end = end;
current.data = '';
return upload(current)
.then(function(){
// do other stuff
return Promise.resolve();
});
});
},Promise.resolve())
.then(function(){
// do other stuff
});
function upload(current) {
if (start < end) {
return new Promise(function(resolve){
var chunk = current.slice(start, temp_end);
var reader = new FileReader();
reader.readAsText(chunk);
reader.onload = function(e) {
if (e.target.readyState == 2) {
current.data += e.target.result;
start = temp_end;
temp_end = start + BYTES_PER_CHUNK;
if (temp_end > end) temp_end = end;
resolve(upload(current));
}
}
});
} else {
return Promise.resolve();
}
}
答案 0 :(得分:3)
你非常接近!您需要使用之前的值;它应该是一个承诺。将reduce的初始值设置为Promise.resolve()
。然后在reduce函数内部,而不是Promise.resolve().then(...)
。你应该有类似的东西:
return previous
.then(function() { return upload(current); })
.then(function() { /* do stuff */ });
你return
在这里很重要。下次调用reduce函数时,这将变为previous
。
upload
功能存在很多问题。 最大问题是你传递变量的方式使得它很难阅读:)(并且容易出错!)
如果您只是阅读文本文件,请改用readAsText
。请注意,我已将其重命名为readFile
,因为这是一个更准确的名称。
// returns a promise with the file contents
function readFile(file) {
return new Promise(function (resolve) {
var reader = new FileReader();
reader.onload = function(e) {
resolve(e.target.result);
};
reader.readAsText(file);
};
}
然后你的减少只是:
files.reduce(function(previous, file) {
return previous
.then(function() { return readFile(file); })
.then(function(contents) {
// do stuff
});
}, Promise.resolve());
但是upload_file
变量有一个很大的错误。该变量是reduce函数范围的本地变量,因此它undefined
位于upload
内。将其作为参数传递:
function upload(upload_file) { ... }
关于var
的附注。这就是为什么即使你在reduce函数中设置upload_file
var
,也就是为upload
调用该函数之前的任何东西:
var a = 3;
function foo() {
var a = 4;
console.log(a); // 4
}
foo();
console.log(a); // 3
&#13;