气势凌人的跑步机 · BufferedReader的读取行数问题_ ...· 1 月前 · |
刚失恋的投影仪 · 为什么BufferedReader读取()比 ...· 1 月前 · |
乐观的卤蛋 · Gitlab-ci:从零开始的前端自动化部署 ...· 1 年前 · |
兴奋的开水瓶 · 获取十六进制模式搜索的前4位数字 - 问答 ...· 1 年前 · |
乐观的蜡烛 · elk安装配置 - 简书· 1 年前 · |
骑白马的山羊 · Read Android NFC Tag ...· 1 年前 · |
我有以下HTML代码:
<input type='file' multiple>
下面是我的JS代码:
var inputFiles = document.getElementsByTagName("input")[0];
inputFiles.onchange = function(){
var fr = new FileReader();
for(var i = 0; i < inputFiles.files.length; i++){
fr.onload = function(){
console.log(i) // Prints "0, 3, 2, 1" in case of 4 chosen files
fr.readAsDataURL(inputFiles.files[i]);
}
所以我的问题是,我如何才能使这个循环同步?,,意思是,首先等待文件加载完成,然后再进入下一个文件。有人告诉我使用JS Promises。但是我不能去上班。这是我正在尝试的:
var inputFiles = document.getElementsByTagName("input")[0];
inputFiles.onchange = function(){
for(var i = 0; i < inputFiles.files.length; i++){
var fr = new FileReader();
var test = new Promise(function(resolve, reject){
console.log(i) // Prints 0, 1, 2, 3 just as expected
resolve(fr.readAsDataURL(inputFiles.files[i]));
test.then(function(){
fr.onload = function(){
console.log(i); // Prints only 3
}
先谢谢你...
发布于 2017-10-04 23:03:02
我们对 midos answer 进行了修改,使其工作起来如下:
function readFile(file){
return new Promise((resolve, reject) => {
var fr = new FileReader();
fr.onload = () => {
resolve(fr.result )
fr.onerror = reject;
fr.readAsText(file.blob);
}
发布于 2015-12-29 09:36:14
如果你想使用Promises按顺序(而不是同步)来做这件事,你可以这样做:
var inputFiles = document.getElementsByTagName("input")[0];
inputFiles.onchange = function(){
var promise = Promise.resolve();
inputFiles.files.map( file => promise.then(()=> pFileReader(file)));
promise.then(() => console.log('all done...'));
function pFileReader(file){
return new Promise((resolve, reject) => {
var fr = new FileReader();
fr.onload = resolve; // CHANGE to whatever function you want which would eventually call resolve
fr.onerror = reject;
fr.readAsDataURL(file);
}
发布于 2015-12-28 23:06:13
FileReader
的本质是您不能使其操作同步。
我怀疑你并不真的需要或希望它是同步的,只是你想要正确地获得结果URL。建议使用promises的人可能是正确的,但这并不是因为promises使流程同步(它们不是),而是因为它们为处理异步操作(无论是并行还是串行)提供了标准化的语义:
使用promise,您可以从
readAsDataURL
的promise包装器开始(我在这里使用ES2015+,但您可以使用promise库将其转换为ES5 ):
function readAsDataURL(file) {
return new Promise((resolve, reject) => {
const fr = new FileReader();
fr.onerror = reject;
fr.onload = () => {
resolve(fr.result);
fr.readAsDataURL(file);
}
然后,您将使用我描述的基于promise的操作 in this answer 来并行读取这些操作:
Promise.all(Array.prototype.map.call(inputFiles.files, readAsDataURL))
.then(urls => {
// ...use `urls` (an array) here...
.catch(error => {
// ...handle/report error...
});
...or系列:
let p = Promise.resolve();
for (const file of inputFiles.files) {
p = p.then(() => readAsDataURL(file).then(url => {
// ...use `url` here...
p.catch(error => {
// ...handle/report error...
});
在ES2017
async
函数中,您可以使用
await
。对于并行版本,它没有做太多的事情:
// Inside an `async` function
try {
const urls = await Promise.all(Array.prototype.map.call(inputFiles.files, readAsDataURL));
} catch (error) {
// ...handle/report error...
}
...but它使该系列版本更简单、更清晰:
// Inside an `async` function
try {
for (const file of inputFiles.files) {
const url = await readAsDataURL(file);
// ...use `url` here...
} catch (error) {
// ...handle/report error...
}
如果没有承诺,你可以通过跟踪你有多少未完成的操作来实现这一点,这样你就知道你什么时候完成了:
const inputFiles = document.getElementsByTagName("input")[0];
inputFiles.onchange = () => {
const data = []; // The results
let pending = 0; // How many outstanding operations we have
// Schedule reading all the files (this finishes before the first onload
// callback is allowed to be executed). Note that the use of `let` in the
// `for` loop is important, `var` would not work correctly.
for (let index = 0; index < inputFiles.files.length; ++index) {
const file = inputFiles.files[index];
// Read this file, remember it in `data` using the same index
// as the file entry
const fr = new FileReader();
fr.onload = () => {
data[index] = fr.result;
--pending;
if (pending == 0) {
// All requests are complete, you're done
fr.readAsDataURL(file);
++pending;
};
或者,如果您出于某种原因希望按顺序读取文件(但仍然是异步的),则可以通过仅在前一次调用完成时安排下一次调用来实现:
// Note: This assumes there is at least one file, if that
// assumption isn't valid, you'll need to add an up-front check
var inputFiles = document.getElementsByTagName("input")[0];
inputFiles.onchange = () => {
let index = 0;
readNext();
function readNext() {
const file = inputFiles.files[index++];
const fr = new FileReader();
fr.onload = () => {
// use fr.result here
if (index < inputFiles.files.length) {
// More to do, start loading the next one