简体   繁体   中英

Calling Resolve function goes to Reject function in JavaScript Promise

I have the following code:

return new Promise (function (resolve,reject) {
        if (this.ImageData && averageColor) {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if (xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) {
                    console.log("Image found");
                    resolve(xhr.response);
                }else {
                    console.log("Image not found");
                    reject();
                }
            }
            xhr.open('GET', 'http://localhost:8765/color/'+averageColor, true);
            xhr.send(null);
        }
        else {
            reject();
        }
    });

The function that calls this code is as follows:

var v =  tile.getImage(tile.getColorAverage());
        v.then(function (value) {
            console.log("laughing");
        }).catch(function () {
           console.log("Catch called");
        });

The issue is in my promise I can see that it is going in that if condition and getting the response from the server correctly (because of the console.log). However, on the other side, it doesn't go into 'then' bit of promise at all (not even once). It goes to the reject one for some reason. I am going nuts as I can see it executes the bit which is supposed to resolve it but I don't get anything in then. Any help would be much appreciated.

Edited:

Now I just ran it once. And here is my console.log trace. Now even more confused:

在此处输入图片说明

xhr.onreadystatechange = function () {
    if (xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) {
        console.log(xhr.response);
        resolve(xhr.response);
    }else {
        reject();
    }
}

The thing about onreadystatechange is, it gets called MULTIPLE times

The thing about promise resolution is that once rejected or resolved, it can not be rejected or resovled again

The first time onreadystatechange gets called, the status would be 1, not 4 ... so you reject

you should only reject if status is 4 and (DONE) AND status != 200

xhr.onreadystatechange = function () {
    if (xhr.readyState == XMLHttpRequest.DONE) {
        if(xhr.status == 200) {
            console.log(xhr.response);
            resolve(xhr.response);
        } else {
            reject();
        }
    }
}

Alternatively, use onload/onerror - though you still need to check for status == 200 in onload

xhr.onload= function () {
    if(xhr.status == 200) {
        console.log(xhr.response);
        resolve(xhr.response);
    } else {
        reject();
    }
}


xhr.onerror= function () {
    reject();
}

as a side note about something that works but looks wrong

return new Promise (function (resolve,reject) {
    if (this.ImageData && averageColor) {

this inside the promise constructor callback could be window , or it even could even be undefined in strict mode - you need to fix that code before it causes issues down the track

The reason you are having this issue is that onreadystatechange is called multiple times before the request completes and before it is DONE you will get your else condition which calls reject . You should only reject if DONE AND xhr.status != 200 . Here is an example:

if (xhr.readyState == XMLHttpRequest.DONE) {
    if (xhr.status == 200) {
        resolve(xhr.response);
    } else {
        reject();
    }
}

this within Promise constructor is window , unless specifically set to a different value. this.ImageData would evaluate to false without setting this to the object that has .ImageData as a property at call to new Promise() .

Substitute reference to object that has property ImageData for this.ImageData within Promise constructor resolver function.

For example

function resolver(resolve, reject) {

}

new Promise(resolver.bind(/*object that has `.ImageData` as property*/))

Also, substitute load event for readystatechange event and include error event handler for XMLHttpRequest object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM