我在Stackoverflow上找到了一些代码,可以从本地磁盘加载文件。一项大功能使一切正常。现在,我试图在较小的函数中将代码分开。
我想将DOM上的所有img.src加载到数组中,并将用户选择的文件添加到数组中。而不是对数组做些什么。
我创建了:
document.getElementById('picField').onchange = function (evt) {
loadImg(evt);
}
async function loadImg(evt) {
let imgInDom = await getImgFromDom();
let allFiles = await loadAllFiles(imgInDom, evt);
console.log(JSON.stringify(allFiles))
//doSometing(allFiles);
setTimeout(() => {
console.log(JSON.stringify(allFiles))
}, 2000);
}
function getImgFromDom() {
return new Promise(resolve => {
let elements = document.getElementsByClassName('loadedImg');
let source = [];
for (x = 0; x < elements.length; x++) {
source.push(elements[x].src)
}
resolve(source);
});
}
function loadAllFiles(imgFromDom, evt) {
return new Promise(resolve => {
let allFiles = [];
let tgt = evt.target || window.event.srcElement,
files = tgt.files;
for (let x = 0; x < files.length; x++) {
// FileReader support
if (FileReader && files && files.length) {
let fr = new FileReader();
fr.readAsDataURL(files[x]);
fr.onload = function () {
allFiles.push(fr.result);
}
}
// Not supported
else {
// fallback -- perhaps submit the input to an iframe and temporarily store
// them on the server until the user's session ends.
}
}
resolve(allFiles);
});
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Arial;
}
.row {
display: flex;
flex-wrap: wrap;
padding: 0 4px;
margin: 30px 60px;
background-color: lightgray;
border-style: ridge;
}
/* Create four equal columns that sits next to each other */
.column {
flex: 25%;
max-width: 25%;
padding: 0 4px;
}
.img-overlay {
position: relative;
width: 100%;
}
.overlay {
position: absolute;
width: 32px;
height: 32px;
top: 6px;
right: 3px;
background-color: Transparent;
background-repeat: no-repeat;
border: none;
cursor: pointer;
overflow: hidden;
outline: none;
}
.column img {
margin-top: 4px;
margin-bottom: 4px;
vertical-align: middle;
width: 100%;
}
/* Responsive layout - makes a two column-layout instead of four columns */
@media screen and (max-width: 800px) {
.column {
min-width: 50%;
}
}
/* Responsive layout - makes the two columns stack on top of each other instead of next to each other */
@media screen and (max-width: 600px) {
.column {
min-width: 100%;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="load">
<input type="file" name="picField" id="picField" size="24" onchange="preview_2(this);" alt="" accept="image/*"
multiple />
</div>
<div class="row">
<div class="column column1">
</div>
<div class="column column2">
</div>
<div class="column column3">
</div>
<div class="column column4">
</div>
</div>
</body>
<script src="/app.js"></script>
</html>
我希望代码会等到loadAllFiles()返回诺言。首先,我认为我的函数存在问题,因为在打印时allFiles是一个空数组。
但是当我将超时设置为2秒时,所有值都在数组中。
有人知道我在做什么错吗?
答案 0 :(得分:1)
您要等待从 getImgFromDom()获取源。因此,我们将此函数用作Promise,并在then
块中等待已解决的结果。当您收到数据时,我们要使用 loadAllFiles()加载文件。在这里,我们接收带有提供的源的文件,并以resolve
返回文件,或者以reject
返回错误。
function loadImg(evt) {
this.getImgFromDom().then(imgInDom => {
this.loadAllFiles(imgInDom, evt)
.then(allFiles => {
// console.log(allFiles) or return the files
})
.catch(error => {
// reject error here
});
})
function getImgFromDom(): Promise<any> {
return new Promise((resolve, reject) => {
// logic here
resolve(source);
});
}
function loadAllFiles(imgFromDom, evt): Promise<any> {
return new Promise((resolve, reject) => {
// logic here
resolve(allFiles);
// error logic here
reject();
});
}
答案 1 :(得分:0)
我通过从fr.onload内解决问题来解决我的问题,就像建议的零298:
function loadAllFiles(imgFromDom, evt) {
return new Promise(resolve => {
let allFiles = [];
allFiles = allFiles.concat(imgFromDom);
let tgt = evt.target || window.event.srcElement,
files = tgt.files;
for (let x = 0; x < files.length; x++) {
// FileReader support
if (FileReader && files && files.length) {
let fr = new FileReader();
fr.readAsDataURL(files[x]);
fr.onload = function () {
allFiles.push(fr.result);
if (x == files.length - 1) {
console.log(allFiles)
resolve(allFiles);
}
}
}
// Not supported
else {
// fallback -- perhaps submit the input to an iframe and temporarily store
// them on the server until the user's session ends.
}
}
});
}
答案 2 :(得分:0)
因为您已经在使用诺言,所以我将它们链接起来。将您的loadImg
方法替换为以下内容:
function loadImg(evt) {
getImgFromDom().then(imgInDom => {
return loadAllFiles(imgInDom, evt)
}).then(allFiles => {
console.log(JSON.stringify(allFiles))
}).catch(error => {
console.warn(error);
});
}
将其与我未经测试编写的免责声明一起使用。 :)