XMLHttpRequest in the browser The intention is to implement an xmlHttpRequest in plain vanilla js while considering all possible errors and problem situations without crashing in the browser. Result and faults are to be properly communicated back to the caller.

function get() {
    return new Promise(function(resolve, reject){
        var xmlHttpRequest = new XMLHttpRequest();
        xmlHttpRequest.open("GET", "http://localhost/products", true);
        xmlHttpRequest.onreadystatechange = function() {
            if (xmlHttpRequest.readyState === 4) {
                try { 
                    var data = JSON.parse(xmlHttpRequest.response);
                } catch (error) { // in case parser error
                    reject(error);
                    return;
                }
                if(xmlHttpRequest.status === 200) {
                    resolve(data);
                } else {
                    reject(data);
                }
            }
        };
        xmlHttpRequest.addEventListener("error", function(error){
            reject(error);
        });
        xmlHttpRequest.send();
    });
}
Here are a few issues with your code


If older browsers aren't a concern, you can just use fetch instead of XHR. It's built-in and uses promises.
HTTP 200 isn't the only "successful" response status. See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes.
Status "0" is a generic network error, not just being offline. It can also be caused by the browser suppressing the request due to some restriction, an extension blocking the request, an insecure connection/invalid certificate.
Send an Accept header with application/json as value. This is because, while the server might support JSON, it might not respond with it by default.
The third argument of xhr.open is by default true. You may omit that third argument.
You can use readystatechange with addEventListener instead of the onreadystatechange property to assign your callback.