[javascript] ¿Cómo promulgo XHR nativo?



Answers

Esto podría ser tan simple como el siguiente código.

Tenga en cuenta que este código solo activará la devolución de llamada reject cuando se onerror (solo errores de red ) y no cuando el código de estado HTTP indique un error. Esto también excluirá todas las demás excepciones. Manejar esos debe depender de usted, OMI.

Además, se recomienda llamar a la devolución de llamada reject con una instancia de Error y no el evento en sí, pero en aras de la simplicidad, dejé como está.

function request(method, url) {
    return new Promise(function (resolve, reject) {
        var xhr = new XMLHttpRequest();
        xhr.open(method, url);
        xhr.onload = resolve;
        xhr.onerror = reject;
        xhr.send();
    });
}

E invocarlo podría ser esto:

request('GET', 'http://google.com')
    .then(function (e) {
        console.log(e.target.response);
    }, function (e) {
        // handle errors
    });
Question

Quiero usar promesas (nativas) en mi aplicación frontend para realizar solicitudes XHR pero sin todas las tonterías de un marco masivo.

Quiero que mi xhr devuelva una promesa, pero esto no funciona (dándome: Uncaught TypeError: Promise resolver undefined is not a function )

function makeXHRRequest (method, url, done) {
  var xhr = new XMLHttpRequest();
  xhr.open(method, url);
  xhr.onload = function() { return new Promise().resolve(); };
  xhr.onerror = function() { return new Promise().reject(); };
  xhr.send();
}

makeXHRRequest('GET', 'http://example.com')
.then(function (datums) {
  console.log(datums);
});



Creo que podemos hacer que la respuesta superior sea mucho más flexible y reutilizable al no tener que crear el objeto XMLHttpRequest . El único beneficio de hacerlo es que no tenemos que escribir 2 o 3 líneas de código para hacerlo, y tiene el enorme inconveniente de quitar nuestro acceso a muchas de las características de la API, como establecer encabezados. También oculta las propiedades del objeto original del código que se supone debe manejar la respuesta (tanto para éxitos como para errores). De modo que podemos hacer una función más flexible y aplicable más ampliamente al aceptar el objeto XMLHttpRequest como entrada y pasarlo como resultado .

Esta función convierte un objeto arbitrario XMLHttpRequest en una promesa, tratando los códigos de estado que no son 200 como un error por defecto:

function promiseResponse(xhr, failNon2xx = true) {
    return new Promise(function (resolve, reject) {
        // Note that when we call reject, we pass an object
        // with the request as a property. This makes it easy for
        // catch blocks to distinguish errors arising here
        // from errors arising elsewhere. Suggestions on a 
        // cleaner way to allow that are welcome.
        xhr.onload = function () {
            if (failNon2xx && (xhr.status < 200 || xhr.status >= 300)) {
                reject({request: xhr});
            } else {
                resolve(xhr);
            }
        };
        xhr.onerror = function () {
            reject({request: xhr});
        };
        xhr.send();
    });
}

Esta función se adapta muy naturalmente a una cadena de Promise , sin sacrificar la flexibilidad de la API XMLHttpRequest :

Promise.resolve()
.then(function() {
    // We make this a separate function to avoid
    // polluting the calling scope.
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://.com/');
    return xhr;
})
.then(promiseResponse)
.then(function(request) {
    console.log('Success');
    console.log(request.status + ' ' + request.statusText);
});

se omitió la catch anterior para mantener el código de muestra más simple. Siempre debes tener uno y, por supuesto, podemos:

Promise.resolve()
.then(function() {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://.com/doesnotexist');
    return xhr;
})
.then(promiseResponse)
.catch(function(err) {
    console.log('Error');
    if (err.hasOwnProperty('request')) {
        console.log(err.request.status + ' ' + err.request.statusText);
    }
    else {
        console.log(err);
    }
});

Y deshabilitar el manejo del código de estado HTTP no requiere mucho cambio en el código:

Promise.resolve()
.then(function() {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://.com/doesnotexist');
    return xhr;
})
.then(function(xhr) { return promiseResponse(xhr, false); })
.then(function(request) {
    console.log('Done');
    console.log(request.status + ' ' + request.statusText);
});

Nuestro código de llamada es más largo, pero conceptualmente, aún es simple entender lo que está sucediendo. Y no tenemos que reconstruir toda la API de solicitud web solo para admitir sus características.

También podemos agregar algunas funciones de conveniencia para poner en orden nuestro código:

function makeSimpleGet(url) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url);
    return xhr;
}

function promiseResponseAnyCode(xhr) {
    return promiseResponse(xhr, false);
}

Entonces nuestro código se convierte en:

Promise.resolve(makeSimpleGet('https://.com/doesnotexist'))
.then(promiseResponseAnyCode)
.then(function(request) {
    console.log('Done');
    console.log(request.status + ' ' + request.statusText);
});





Related