猿问

如何在循环内使用回调?

背景是我允许用户将多个文件拖入 Dropzone。我需要检查每种文件类型。如果其中一个不允许,设置消息并早点离开。


请参阅下面的代码 Starts at for (let i = 0; i < acceptedFiles.length; i++) { Inside this for loop, I call reader.onloadend,这是一个回调。


如何在 for 循环中运行回调?


// Keep it internal

  const getMimetype = signature => {

    switch (signature) {

      case '89504E47':

        return 'image/png';

      case '47494638':

        return 'image/gif';

      case '25504446':

        return 'application/pdf';

      case 'FFD8FFDB':

      case 'FFD8FFE0':

        return 'image/jpeg';

      case '504B0304':

        return 'application/zip';

      default:

        return 'Unknown filetype';

    }

  };


  const onDropAccepted = useCallback(acceptedFiles => {

    // reset to default state

    resetToDefaultState();


    //test

    console.log('acceptedFiles', acceptedFiles);


    // reader

    const reader = new FileReader();

    let file;


    // Multi

    if (config.isMultipleFiles === true) {

      // Loop all files and check file types

      for (let i = 0; i < acceptedFiles.length; i++) {

        file = acceptedFiles[i];

        // get 1st 4 byptes

        const blob = file.slice(0, 4);

        reader.readAsArrayBuffer(blob);


        reader.onloadend = evt => {

          if (evt.target.readyState === FileReader.DONE) {

            const uint = new Uint8Array(evt.target.result);

            let bytes = [];

            uint.forEach(byte => {

              bytes.push(byte.toString(16));

            });


            const hex = bytes.join('').toUpperCase();

            const type = getMimetype(hex);


            // type is allowed

            if (config.fileTypes.includes(type)) {

              setFiles([...files, ...acceptedFiles]);

            } else {

              // type no good

              setIsInvaildFileType(true);

            }

          }

        };

      }

    } 

慕妹3242003
浏览 178回答 1
1回答

慕桂英546537

我还必须以react-dropzone类似的方式验证每个文件。我的解决方法是承诺FileReader.1️⃣ This is the promisified version of "FileReader"const isValidFile = file => {&nbsp; return new Promise((resolve, reject) => {&nbsp; &nbsp; const reader = new FileReader();&nbsp; &nbsp; reader.onloadend = evt => {&nbsp; &nbsp; &nbsp; // other logic removed for brevity...&nbsp; &nbsp; &nbsp; 2️⃣ Your custom logic dictates, if the file is valid or not&nbsp; &nbsp; &nbsp; if (config.fileTypes.includes(type)) {&nbsp; &nbsp; &nbsp; &nbsp; resolve(true);&nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; resolve(false);&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; };&nbsp; &nbsp; 3️⃣ Should there was an error, this file is not good.&nbsp; &nbsp; reader.onerror = () => resolve(false)&nbsp; &nbsp; 4️⃣ Start the reading process.&nbsp; &nbsp; const blob = file.slice(0, 4);&nbsp; &nbsp; reader.readAsArrayBuffer(blob);&nbsp; });};现在您可以在for您提到的循环中使用它。const onDropAccepted = useCallback(acceptedFiles => {&nbsp; // reset to default state&nbsp; resetToDefaultState();&nbsp; 1️⃣ As `useCallback` accepts a non-async method,&nbsp; &nbsp; &nbsp; Create a wrapped async method we can call here.&nbsp; const processFiles = async () => {&nbsp; &nbsp; if (config.isMultipleFiles === true) {&nbsp; &nbsp; &nbsp; for (let i = 0; i < acceptedFiles.length; i++) {&nbsp; &nbsp; &nbsp; &nbsp; const file = acceptedFiles[i];&nbsp; &nbsp; &nbsp; &nbsp; 2️⃣ Here is where we validate the file using the code above.&nbsp; &nbsp; &nbsp; &nbsp; const isValid = await isValidFile(file);&nbsp; &nbsp; &nbsp; &nbsp; if (!isValid) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setIsInvaildFileType(true);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; 3️⃣ At this point, all files are good.&nbsp; &nbsp; &nbsp; setFiles([...files, ...acceptedFiles]);&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; // removed for brevity...&nbsp; &nbsp; }&nbsp; };&nbsp; 4️⃣ Let's fire up the process&nbsp; processFiles();});
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答