我如何宣传原生XHR? [英] How do I promisify native XHR?
问题描述
我想在我的前端应用程序中使用(本机)promises来执行XHR请求,但没有庞大框架的所有tomfoolery。
I want to use (native) promises in my frontend app to perform XHR request but without all the tomfoolery of a massive framework.
我希望我的xhr返回承诺,但这不起作用(给我:未捕获TypeError:承诺解析器未定义不是函数
)
I want my xhr to return a promise but this doesn't work (giving me: 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请求(您可以在这里刷新 和这里)
I'm assuming you know how to make a native XHR request (you can brush up here and here)
由于支持本机承诺的任何浏览器也将支持 xhr.onload
,我们可以跳过所有 onReadyStateChange
tomfoolery。让我们退后一步,使用回调函数从基本的XHR请求函数开始:
Since any browser that supports native promises will also support xhr.onload
, we can skip all the onReadyStateChange
tomfoolery. Let's take a step back and start with a basic XHR request function using callbacks:
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);
});
Hurray!这不涉及任何非常复杂的事情(如自定义标题或POST数据),但足以让我们向前移动。
Hurrah! This doesn't involve anything terribly complicated (like custom headers or POST data) but is enough to get us moving forwards.
我们可以像这样构建一个承诺:
We can construct a promise like so:
new Promise(function (resolve, reject) {
// Do some Async stuff
// call resolve if it succeeded
// reject if it failed
});
promise构造函数接受一个将传递两个参数的函数(让我们称之为解决
和拒绝
)。您可以将这些视为回调,一个用于成功,一个用于失败。示例很棒,让我们用这个构造函数更新 makeRequest
:
The promise constructor takes a function that will be passed two arguments (let's call them resolve
and reject
). You can think of these as callbacks, one for success and one for failure. Examples are awesome, let's update makeRequest
with this constructor:
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);
});
现在我们可以利用承诺的力量,链接多个XHR呼叫(以及 .catch
将在任一调用中触发错误):
Now we can tap into the power of promises, chaining multiple XHR calls (and the .catch
will trigger for an error on either call):
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参数和自定义标题。让我们使用选项对象而不是多个参数,使用签名:
We can improve this still further, adding both POST/PUT params and custom headers. Let's use an options object instead of multiple arguments, with the signature:
{
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 。
Alternatively, you could use the fetch API (polyfill).
这篇关于我如何宣传原生XHR?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!