0

I am new to Promises and I am sure I am doing something wrong with my code. The result is correct but I have an Uncaught (in promise) warning in my console.log. What is going on here is the User can submit a form where there are some required fields, some optional fields and an image. On submit I am getting the image that gets compressed, resized and oriented so that it upload to the server as a small amount of Kbs.

In the coontroller I validate the code as said, some fields are required so in the error case inside the Ajax call I get the textStatus if a field is missing.

What happens with this code is that if the user inputs the image but none or some of the required fields the XHR textstatus error object appears as Uncaught (in promise), (The missing required fields).

I am missing the point of how you deal with errors (reject ? ) in promises so I don't really know how to solve this one.

My guess is that if the User submits the image but not the required fields there should be a way to check that during the promise so that it gets rejected even if the user submitted the image (as the image alone does not suffice). Is this done with reject ? But where? and how do you call the error after .then() ? And what if the user submits some required fields or all of them but not the image? If I let the promise run I get an undefined error in the promise, that's why I added a check to see if there's any file and if it's an image.

This is my script:

$(document).ready(function () {

    $("#AddModel").on("submit", function (e) {

        e.preventDefault();

        // gets the file from the form input
        var files = $('#modelpic').prop('files');

        var form = $(this);

        // this strips the submitted form from the file and returns a new form with all the
        // inputs but the file
        var processedFormData = noFileFormData(form[0]);

        // only if there's a file and it's an image
        if( files.length !== 0 && /^image/.test(files[0].type)){

            //this calls the promise that manipulates the image and returns a blob
            processImage(files[0]).then(([img, ia])=> {

                processedFormData.append('image', ia, 'processed.jpg');

                return $.ajax({
                    type: 'POST',
                    url: form.prop('action'),
                    processData: false,
                    contentType: false,
                    cache: false,
                    data: processedFormData,
                    success: function (data) {

                        //displays preview of the post

                    },

                    error: function (textStatus) {

                        //displays errors


                    }
                });

            });
        }else{

                //displays an error re the image is not present.
                // Now this is not optimal as the image is not the only required field

        }
    });
});

This is the promise function that prepares the manipulated image, it calls some other functions for the real processing:

function processImage(file) {

    return new Promise(function (resolve, reject) {

        if (file.type.match('image.*') && file.length != 0) {

            var reader = new FileReader();

            reader.readAsDataURL(file);

            reader.onloadend = function () {

                var base64img = this.result;

                var exif = EXIF.readFromBinaryFile(base64ToArrayBuffer(this.result));
                var srcOrientation = exif.Orientation;

                resetOrientationResizeCompress(base64img, srcOrientation).then((img)=> {

                    dataURItoBlob(img).then((ia)=> {

                        resolve([img, ia]);

                    });

                });
            };
        }else{

            //don't really know what to do here really, or if this is the way

            reject();

        }
    });
}
Chriz74
  • 1,410
  • 3
  • 23
  • 47
  • 1
    Well yes, you don't handle any rejections of that `processImage(…).then(…)` promise? Just append a `.catch(console.error)` to that chain. – Bergi Jun 01 '17 at 21:29
  • 1
    Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! Do `resolve(this.result)` only, and do all the other stuff in a `then` handler. – Bergi Jun 01 '17 at 21:30
  • Ok, appending the `.catch(console.error)` to the chain made the uncaught error disappear. The question is, what do I do with that console.error object? And also where is the anti pattern in the code above? – Chriz74 Jun 05 '17 at 13:09
  • Well, what do you *want* to do with errors? – Bergi Jun 05 '17 at 13:13
  • Well I am already showing input errors in `error: function (textStatus)` , the object that I get with the `.catch(console.error)` contains the same data. – Chriz74 Jun 05 '17 at 13:14
  • Uh, yes, don't do that. Use `then` instead of passing callbacks to the ajax request. Also the `.catch(…)` in the end will also deal with errors from the other actions in the chain – Bergi Jun 05 '17 at 13:17

1 Answers1

4

It is telling you that you are not catching the error rejection, append .catch to the processImage(files[0]) promise.

Faris
  • 544
  • 2
  • 8