javascriptimagevue.jscompressiondropzone

Uncaught TypeError: this.testFunction is not a function


I've got a Vue app with an upload component which gets an image (dropzone), pass it to cropper (cropperjs) and returns it to dropzone once cropped. I want to compress image just before the upload, so i'm gonna get the image from the dropzone object and pass it to the compressor (compressorjs). I'm struggling with an error and can't go further.. that's the situation:

Cropping method:

cropImage() {
            // get image data for post processing, e.g. upload or setting image src
            this.$refs.cropper.getCroppedCanvas().toBlob((blob)=> {
                var croppedFile = this.blobToFile(blob, this.fileName)
                croppedFile.accepted = true
                this.$refs.myVueDropzone.dropzone.addFile(croppedFile)
                this.cropperReset()
            });
        },

At this point my dropzone gets the cropped images and produces correctly the cropper thumbnail.
Now i'm gonna to launch the upload method, but compressing the image just before processing the queue.

launchUpload() {
            new Compressor(this.$refs.myVueDropzone.dropzone.files[0], {
                quality: 0.6,
                maxWidth: 250,
                minWidth: 250,
                success(compressedResult){
                    this.testFunction(compressedResult)
                },
                error(err) {
                    console.log(err.message);
                },
            })

            /*await this.$refs.myVueDropzone.processQueue()
            this.$refs.myVueDropzone.removeAllFiles()*/
        }

I'm gonna pass the file to the Compressor, pass some settings and getting the "compressedResult" blob which is the compressed version of the image. My problem is that using testFunction into it results in:

"Uncaught TypeError: this.testFunction is not a function"

testFunction is just a dummy function that i made after trying everything else..

testFunction(compressed){
            this.$refs.myVueDropzone.removeAllFiles()
            this.$refs.myVueDropzone.addFile(compressed)
        },

console.log into testFunction results "undefined" and nothing seems to work..
Every method i posted here is part of "methods" objects of the Vue component.

Vue part where the components interact:

<v-dialog
            v-model="is_show"
            persistent
            max-width="800px"
        >
            <v-card>
                <v-card-title>
                    <span class="text-h5">Upload File</span>
                </v-card-title>
                <v-card-text>
                    <vue-dropzone
                        ref="myVueDropzone"
                        id="dropzone"
                        :options="dropzoneOptions"
                        @vdropzone-file-added="(file) => passToCropper(file)"
                        @vdropzone-complete="reloadAndClose"
                    ></vue-dropzone>
                    <v-col cols="12" class="text-right">
                        <v-btn
                            @click="closeModal"
                            class="ma-2"
                            :disabled="loading"
                        >
                            Close
                        </v-btn>
                        <v-btn
                            @click="launchUpload"
                            class="ma-2"
                            color="primary"
                            :loading="loading"
                        >
                            Submit
                        </v-btn>
                    </v-col>
                </v-card-text>
            </v-card>
        </v-dialog>

Everything works perfectly if i don't compress the image and process my dropzone queue just after the "addFile" part into cropImage method.
Many thanks!!


Solution

  • You should use an arrow function expression instead of a function expression because using a function expression it creates its own this binding.

    So in your case testFunction doesn't exist in the new context (the new this).

    success(compressedResult){
        this.testFunction(compressedResult)
     },
    

    See how this refers to the global object in case of an arrow function expression and how this refers to the object the method is called on in case of a function expression :

    const obj = {
      someProperty: 'someProperty',
      a: () => {
        console.log(this === window, this === obj)
      },
      b() {
        console.log(this === window, this === obj)
      }
    }
    
    obj.a()
    obj.b()

    You can also keep your function expression and use a stored reference of this like :

    launchUpload() {
        const that = this;
        new Compressor(this.$refs.myVueDropzone.dropzone.files[0], {
            quality: 0.6,
            maxWidth: 250,
            minWidth: 250,
            success(compressedResult){
                that.testFunction(compressedResult)
            },
            error(err) {
                console.log(err.message);
            },
        })
    
        /*await this.$refs.myVueDropzone.processQueue()
        this.$refs.myVueDropzone.removeAllFiles()*/
    }