Подождите, пока не вернется обещание - PullRequest
0 голосов
/ 20 июня 2019

Я нашел код здесь, в Stackoverflow, для загрузки файлов с вашего локального диска.Все отлично работало в одной большой функции.Теперь я попытался разбить код на более мелкие функции.

Я хочу загрузить все img.src в DOM в массиве и добавить файлы, выбранные пользователем, в массив.А чем что-то делать с массивом.

Я создал:

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 секунды, все значения находятся в массиве.

Кто-нибудь знает, что я делаю неправильно?

Ответы [ 3 ]

1 голос
/ 21 июня 2019

Вы хотите подождать, чтобы получить источник от getImgFromDom () .Поэтому мы используем эту функцию в качестве Обещания и ждем разрешенного результата в блоке 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();
  });
}
0 голосов
/ 22 июня 2019

Поскольку вы уже используете обещания, я бы их связал. Замените ваш loadImg метод следующим:

function loadImg(evt) {
    getImgFromDom().then(imgInDom => {
      return loadAllFiles(imgInDom, evt)
    }).then(allFiles => {
      console.log(JSON.stringify(allFiles))
    }).catch(error => {
      console.warn(error);
    });
}

Используйте это с заявлением об отказе от ответственности, которое я только что написал без тестирования. :)

0 голосов
/ 22 июня 2019

Я решаю свою проблему, решая изнутри 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.
            }
        }


    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...