function request(options) {
return new Promise((resolve, reject) => {
if (!options || !options.url) {
reject(new Error('URL is required'));
return;
}
const xhr = new XMLHttpRequest();
const {
url,
method = 'GET',
data = null,
headers = {},
timeout = 10000,
responseType = ''
} = options;
xhr.open(method.toUpperCase(), url, true);
if (responseType) {
xhr.responseType = responseType;
}
xhr.timeout = timeout;
xhr.ontimeout = () => {
reject(new Error(`Request timed out after ${timeout}ms`));
};
if (data && !headers['Content-Type']) {
xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
}
Object.keys(headers).forEach(key => {
xhr.setRequestHeader(key, headers[key]);
});
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
try {
const response = responseType === 'json' || xhr.getResponseHeader('Content-Type')?.includes('application/json')
? JSON.parse(xhr.responseText)
: xhr.response;
resolve(response);
} catch (e) {
reject(new Error('Failed to parse response as JSON'));
}
} else {
reject(new Error(`Request failed with status ${xhr.status}: ${xhr.statusText}`));
}
};
xhr.onerror = () => {
reject(new Error('Network request failed'));
};
try {
xhr.send(data ? (typeof data === 'string' ? data : JSON.stringify(data)) : null);
} catch (e) {
reject(new Error(`Failed to send request: ${e.message}`));
}
});
}
request({
url: 'https://jsonplaceholder.typicode.com/posts/1',
method: 'GET'
})
.then(response => console.log('GET Success:', response))
.catch(error => console.error('GET Error:', error));
request({
url: 'https://jsonplaceholder.typicode.com/posts',
method: 'POST',
data: {
title: 'foo',
body: 'bar',
userId: 1
},
headers: {
'X-Custom-Header': 'value'
}
})
.then(response => console.log('POST Success:', response))
.catch(error => console.error('POST Error:', error));
request({
url: 'https://jsonplaceholder.typicode.com/posts/1',
method: 'GET',
timeout: 5000
})
.then(response => console.log('Timeout Success:', response))
.catch(error => console.error('Timeout Error:', error));