0
const filesHandler = (_files: File[]) => {

        for (let i = 0; i < _files.length; i++) {
            let file = _files[i]

            if (file?.type.startsWith("image/")) {
                let name = file.name.split('.')[0]
                postPartNames[i] = name;
                postPartFiles[i] = file;
                let reader = new FileReader();

                reader.readAsDataURL(file)
                reader.onload = () => {
                    postPartSrc[i] = reader.result  
                }
            }
        }
}

У меня есть вот такая функция, мне надо, чтобы после того как FileReader Загрузит все файлы, у меня запустилась другая функция, как мне это сделать ?

ps1Xt
  • 55
  • 3
  • Можно в onload считать сколько уже загружено и выполнить действие, когда загружены все. – vp_arth Dec 05 '20 at 20:04
  • Так и сделал, просто думал, может есть какой-то более элегантный способ :) – ps1Xt Dec 05 '20 at 20:06
  • FileReader.onloadend – Aziz Umarov Dec 05 '20 at 20:11
  • https://developer.mozilla.org/ru/docs/Web/API/FileReader – Aziz Umarov Dec 05 '20 at 20:11
  • 3
    А по хорошему. Создавайте промисы. И Promise.All. чтоб сделать единый обработчик для всех файлов – Aziz Umarov Dec 05 '20 at 20:13
  • Вот пример не promise.all но с promise https://stackoverflow.com/questions/34495796/javascript-promises-with-filereader – Aziz Umarov Dec 05 '20 at 20:17

2 Answers2

-1

как бы я написал. (конечно же ответ на вопрос это второй пример)

песочница там

как мне кажется, в обоих случаях стоит обратить внимание на обработку reader.onerror

module ORIGIN {
    export class Data {
        constructor(
            public name: string,
            public file: File,
            public result?: string | ArrayBuffer | null,
        ) { }
    }
    export const postPart = new Map<number, Data>()
    export const filesHandler = (fileList: File[]) => {
        for (let i = 0; i < fileList.length; i++) {
            const file = fileList[i]
            if (file?.type.startsWith("image/")) foo(file, i)
        }
    }
function foo(file: File, i: number) {
    const name = file.name.split('.')[0]
    const reader = new FileReader();
    reader.readAsDataURL(file)
    reader.onload = () =&gt; {
        postPart.set(i, new Data(name, file, reader.result))
    }
    reader.onerror = () =&gt; {
        // TODO:
        postPart.set(i, new Data(name, file, null))
    }
}

}

module Q1 {
    class Data {
        constructor(
            public name: string,
            public file: File,
            public result?: string | ArrayBuffer | null,
        ) { }
        static genPromise = (data: Data) => {
            return new Promise<Data>((resolve, reject) => {
                if (data.result) {
                    resolve(data)
                } else {
                    const reader = new FileReader();
                    reader.onload = onload
                    reader.onerror = onerror
                    reader.readAsDataURL(data.file)

                    function onload(this: FileReader, ev: ProgressEvent<FileReader>) {
                        data.result = reader.result
                        resolve(data)
                    }
                    function onerror(this: FileReader, ev: ProgressEvent<FileReader>) {
                        reject()
                    }
                }
            })
        }
    }

    export const filesFilter = (fileList: File[], key: string) =>
        fileList.filter(file => file?.type.startsWith(key))

    export const filesHandlerPromise = (fileList: File[]) =>
        fileList.map(file => {
            const name = file.name.split('.')[0]
            return Data.genPromise(new Data(name, file))
        })

    export const filesHandler = (fileList: File[]) =>
        fileList.map(file => {
            const name = file.name.split('.')[0]
            return new Data(name, file)
        })
}

{//test
    const fileList: File[] = null as any
    {//ex1
        Promise
            .all(
                Q1.filesHandlerPromise(Q1.filesFilter(fileList, 'image/'))
            )
            .then(dataList => {
                dataList.forEach(data => {
                    console.log(data.name)
                })
            })
    }
    {//ex2
        void async function () {
            const dataList = await Promise.all(Q1.filesHandlerPromise(Q1.filesFilter(fileList, 'image/')))

            dataList.forEach(data => {
                console.log(data.name)
            })
        }()
    }
}
qwabra
  • 4,962
-1

Можно решить через async/await и Promise

const filesHandler = (files: File[]): Promise<any> => {
  const out = files
    .filter(f => f?.type.startsWith("image/"))
    .map((f) => {
      let name = f.name.split('.')[0]
  const fileResult = {
    name, 
    file: f,
    result: null,
    error: null,
  };

  return new Promise((resolve, reject) =&gt; {
    let reader = new FileReader();
    reader.readAsDataURL(f)
    reader.onload = () =&gt; {
      fileResult.result = reader.result;
      resolve(fileResult);
    };
    reader.onerror = (err) =&gt; {
      fileResult.error = err;
      reject(fileResult);
    };
  });
});

return Promise.all(out); }

// Использовать const loadedFiles = await filesHandler(files);

mego4iter
  • 499