我如何宣传原生XHR?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我如何宣传原生XHR?相关的知识,希望对你有一定的参考价值。
我想在我的前端应用程序中使用(本机)promises来执行XHR请求,但没有庞大框架的所有tomfoolery。
我希望我的xhr返回一个承诺,但这不起作用(给我: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);
);
我假设您知道如何制作原生XHR请求(您可以刷新here和here)
由于any browser that supports native promises也将支持xhr.onload
,我们可以跳过所有onReadyStateChange
tomfoolery。让我们退一步,从使用回调的基本XHR请求函数开始:
function makeRequest (method, url, done)
var xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function ()
done(null, xhr.response);
;
xhr.onerror = function ()
done(xhr.response);
;
xhr.send();
// And we'd call it as such:
makeRequest('GET', 'http://example.com', function (err, datums)
if (err) throw err;
console.log(datums);
);
欢呼!这不涉及任何非常复杂的事情(如自定义标题或POST数据),但足以让我们前进。
承诺构造函数
我们可以这样构建一个承诺:
new Promise(function (resolve, reject)
// Do some Async stuff
// call resolve if it succeeded
// reject if it failed
);
promise构造函数接受一个将传递两个参数的函数(让我们称之为resolve
和reject
)。您可以将这些视为回调,一个用于成功,一个用于失败。示例很棒,让我们用这个构造函数更新makeRequest
:
function makeRequest (method, url)
return new Promise(function (resolve, reject)
var xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function ()
if (this.status >= 200 && this.status < 300)
resolve(xhr.response);
else
reject(
status: this.status,
statusText: xhr.statusText
);
;
xhr.onerror = function ()
reject(
status: this.status,
statusText: xhr.statusText
);
;
xhr.send();
);
// Example:
makeRequest('GET', 'http://example.com')
.then(function (datums)
console.log(datums);
)
.catch(function (err)
console.error('Augh, there was an error!', err.statusText);
);
现在我们可以利用promises的功能,链接多个XHR调用(并且.catch
将在任一调用中触发错误):
makeRequest('GET', 'http://example.com')
.then(function (datums)
return makeRequest('GET', datums.url);
)
.then(function (moreDatums)
console.log(moreDatums);
)
.catch(function (err)
console.error('Augh, there was an error!', err.statusText);
);
我们可以进一步改进这一点,添加POST / PUT参数和自定义标题。让我们使用选项对象而不是多个参数,签名:
method: String,
url: String,
params: String | Object,
headers: Object
makeRequest
现在看起来像这样:
function makeRequest (opts)
return new Promise(function (resolve, reject)
var xhr = new XMLHttpRequest();
xhr.open(opts.method, opts.url);
xhr.onload = function ()
if (this.status >= 200 && this.status < 300)
resolve(xhr.response);
else
reject(
status: this.status,
statusText: xhr.statusText
);
;
xhr.onerror = function ()
reject(
status: this.status,
statusText: xhr.statusText
);
;
if (opts.headers)
Object.keys(opts.headers).forEach(function (key)
xhr.setRequestHeader(key, opts.headers[key]);
);
var params = opts.params;
// We'll need to stringify if we've been given an object
// If we have a string, this is skipped.
if (params && typeof params === 'object')
params = Object.keys(params).map(function (key)
return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
).join('&');
xhr.send(params);
);
// Headers and params are optional
makeRequest(
method: 'GET',
url: 'http://example.com'
)
.then(function (datums)
return makeRequest(
method: 'POST',
url: datums.url,
params:
score: 9001
,
headers:
'X-Subliminal-Message': 'Upvote-this-answer'
);
)
.catch(function (err)
console.error('Augh, there was an error!', err.statusText);
);
在MDN可以找到更全面的方法。
这可以像下面的代码一样简单。
请记住,此代码仅在调用reject
时触发onerror
回调(仅限网络错误),而不是在HTTP状态代码表示错误时触发。这也将排除所有其他例外情况。处理这些应该取决于你,IMO。
另外,建议使用reject
的实例调用Error
回调而不是事件本身,但为了简单起见,我保持原样。
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();
);
并调用它可能是这样的:
request('GET', 'http://google.com')
.then(function (e)
console.log(e.target.response);
, function (e)
// handle errors
);
对于现在搜索此内容的任何人,您都可以使用fetch函数。它有一些非常好的support。
我首先使用@ SomeKittens的答案,但后来发现fetch
为我开箱即用:)
我认为我们可以通过不创建the top answer对象来使XMLHttpRequest
更加灵活和可重用。这样做的唯一好处是我们不必自己编写2或3行代码,并且它具有取消对API的许多功能(如设置标头)的巨大缺点。它还从应该处理响应的代码中隐藏原始对象的属性(对于成功和错误)。因此,我们可以通过接受XMLHttpRequest
对象作为输入并将其作为结果传递来制作更灵活,更广泛适用的函数。
此函数将任意XMLHttpRequest
对象转换为promise,默认情况下将非200状态代码视为错误:
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();
);
这个函数非常自然地适合Promise
s链,而不会牺牲XMLHttpRequest
API的灵活性:
Promise.resolve()
.then(function()
// We make this a separate function to avoid
// polluting the calling scope.
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://stackoverflow.com/');
return xhr;
)
.then(promiseResponse)
.then(function(request)
console.log('Success');
console.log(request.status + ' ' + request.statusText);
);
上面省略了catch
以使示例代码更简单。你应该总是有一个,当然我们可以:
Promise.resolve()
.then(function()
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://stackoverflow.com/doesnotexist');
return xhr;
)
.then(promiseResponse)
.catch(function(err)
console.log('Error');
if (err.hasOwnProperty('request'))
console.error(err.request.status + ' ' + err.request.statusText);
else
console.error(er以上是关于我如何宣传原生XHR?的主要内容,如果未能解决你的问题,请参考以下文章