Javascript,使用 Promises 在 Array.reduce 中上传多个文件,怎么样?
Javascript, uploading several files within an Array.reduce with Promises, how?
从 演变而来,它向我展示了 Promise 如何也可以解析一个函数,现在我坚持使用相同的方法,但在 Array.reduce 函数中。
我的目标是我想在一个数组中上传一个文件(已经上传),其中每个数组项(一个文件)都是按顺序上传的(即通过承诺控制)。
然后,我知道答案不知何故在 http://www.html5rocks.com/en/tutorials/es6/promises/?redirect_from_locale=es 中,但我不明白如何将其应用到这里。我的数组不是承诺数组,而是文件数组。好吧,整件事对我来说仍然很模糊。
这是我的代码,如果我能看到 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 uploading_file,开始,temp_end,结束,内容;
var BYTES_PER_CHUNK = 100000;
我的Array.reduce(函数(上一个,当前){
return 上一个
.then(函数() {
BYTES_PER_CHUNK = 100000;
开始= 0;
temp_end = 开始 + BYTES_PER_CHUNK;
end = parseInt(current.size);
如果(temp_end > 结束)temp_end = 结束;
内容 = '';
uploading_file = 当前;
upload()
.then(function(content){
// do stuff with "content"
console.log('here')
return Promise.resolve();
});
});
},Promise.resolve())
.then(函数(){
console.log('ein');
});
函数上传(){
如果(开始<结束){
return 新承诺(功能(解决){
var chunk = uploading_file.slice(开始, temp_end);
var reader = new FileReader();
reader.readAsArrayBuffer(块);
reader.onload = 函数(e) {
如果(e.target.readyState == 2){
内容 += 新的 TextDecoder("utf-8").decode(e.target.result);
开始 = temp_end;
temp_end = 开始 + BYTES_PER_CHUNK;
如果(temp_end > 结束)temp_end = 结束;
解决(上传());
}
}
});
} 别的 {
uploading_file = 空;
return Promise.resolve(内容);
}
}
改进的代码,似乎可以工作,也许更容易阅读?
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();
}
}
你非常接近!您需要使用之前的值;这应该是一个承诺。将 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);
};
}
那么你的 reduce 就是:
files.reduce(function(previous, file) {
return previous
.then(function() { return readFile(file); })
.then(function(contents) {
// do stuff
});
}, Promise.resolve());
但是 upload_file
变量有一个大错误。该变量在 reduce 函数的范围内是局部的,因此它会在 upload
内 undefined
。而是将其作为参数传递:
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
从
我的目标是我想在一个数组中上传一个文件(已经上传),其中每个数组项(一个文件)都是按顺序上传的(即通过承诺控制)。
然后,我知道答案不知何故在 http://www.html5rocks.com/en/tutorials/es6/promises/?redirect_from_locale=es 中,但我不明白如何将其应用到这里。我的数组不是承诺数组,而是文件数组。好吧,整件事对我来说仍然很模糊。
这是我的代码,如果我能看到 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 uploading_file,开始,temp_end,结束,内容; var BYTES_PER_CHUNK = 100000;
我的Array.reduce(函数(上一个,当前){ return 上一个 .then(函数() { BYTES_PER_CHUNK = 100000; 开始= 0; temp_end = 开始 + BYTES_PER_CHUNK; end = parseInt(current.size); 如果(temp_end > 结束)temp_end = 结束; 内容 = ''; uploading_file = 当前;
upload() .then(function(content){ // do stuff with "content" console.log('here') return Promise.resolve(); });
}); },Promise.resolve()) .then(函数(){ console.log('ein'); });
函数上传(){ 如果(开始<结束){ return 新承诺(功能(解决){ var chunk = uploading_file.slice(开始, temp_end); var reader = new FileReader(); reader.readAsArrayBuffer(块); reader.onload = 函数(e) { 如果(e.target.readyState == 2){ 内容 += 新的 TextDecoder("utf-8").decode(e.target.result); 开始 = temp_end; temp_end = 开始 + BYTES_PER_CHUNK; 如果(temp_end > 结束)temp_end = 结束; 解决(上传()); } } }); } 别的 { uploading_file = 空; return Promise.resolve(内容); } }
改进的代码,似乎可以工作,也许更容易阅读?
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(); } }
你非常接近!您需要使用之前的值;这应该是一个承诺。将 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);
};
}
那么你的 reduce 就是:
files.reduce(function(previous, file) {
return previous
.then(function() { return readFile(file); })
.then(function(contents) {
// do stuff
});
}, Promise.resolve());
但是 upload_file
变量有一个大错误。该变量在 reduce 函数的范围内是局部的,因此它会在 upload
内 undefined
。而是将其作为参数传递:
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