fetch/fetch.js

190 строки
4.2 KiB
JavaScript

(function() {
'use strict';
if (window.fetch) {
return
}
function Headers(headers) {
this.map = {}
if (headers instanceof Headers) {
headers.forEach(function(name, values) {
values.forEach(function(value) {
this.append(name, value)
})
})
} else if (headers) {
Object.getOwnPropertyNames(headers).forEach(function(name) {
this.append(name, headers[name])
})
}
}
Headers.prototype.append = function(name, value) {
var list = this.map[name]
if (!list) {
list = []
this.map[name] = list
}
list.push(value)
}
Headers.prototype.delete = function(name) {
delete this.map[name]
}
Headers.prototype.get = function(name) {
var values = this.map[name]
return values ? values[0] : null
}
Headers.prototype.getAll = function(name) {
return this.map[name] || []
}
Headers.prototype.has = function(name) {
return this.map.hasOwnProperty(name)
}
Headers.prototype.set = function(name, value) {
this.map[name] = [value]
}
// Instead of iterable for now.
Headers.prototype.forEach = function(callback) {
Object.getOwnPropertyNames(this.map).forEach(function(name) {
callback(name, this.map[name])
})
}
function Body() {
this.body = null
this.bodyUsed = false
this.arrayBuffer = function() {
throw 'Not implemented yet'
}
this.blob = function() {
return Promise.resolve(new Blob([this.body]))
}
this.formData = function() {
throw 'Not implemented yet'
}
this.json = function() {
var body = this.body
return new Promise(function(resolve, reject) {
try {
resolve(JSON.parse(body))
} catch (ex) {
reject(ex)
}
})
}
this.text = function() {
return Promise.resolve(this.body)
}
return this
}
function Request(url, options) {
options = options || {}
this.url = url
this.body = options.body
this.credentials = options.credentials || null
this.headers = new Headers(options.headers)
this.method = options.method || 'GET'
this.mode = options.mode || null
this.referrer = null
}
function encode(params) {
var pairs = Object.getOwnPropertyNames(params).map(function(name) {
var key = encodeURIComponent(name)
var value = encodeURIComponent(params[name])
return [key, value].join('&')
})
return pairs.join('&')
}
function isObject(value) {
try {
return Object.getPrototypeOf(value) === Object.prototype
} catch (ex) {
// Probably a string literal.
return false
}
}
function headers(xhr) {
var headers = new Headers()
var pairs = xhr.getAllResponseHeaders().trim().split("\n")
pairs.forEach(function(header) {
var split = header.trim().split(':')
var key = split.shift().trim()
var value = split.join(':').trim()
headers.append(key, value)
})
return headers
}
Request.prototype.fetch = function() {
var self = this
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest()
xhr.onload = function() {
var options = {
status: xhr.status,
statusText: xhr.statusText,
headers: headers(xhr)
}
resolve(new Response(xhr.responseText, options))
}
xhr.onerror = function() {
reject()
}
xhr.open(self.method, self.url)
self.headers.forEach(function(name, values) {
values.forEach(function(value) {
xhr.setRequestHeader(name, value)
})
})
var body = self.body
if (isObject(self.body)) {
xhr.setRequestHeader('application/x-www-form-urlencoded;charset=UTF-8')
body = encode(self.body)
}
xhr.send(body)
})
}
Body.call(Request.prototype)
function Response(body, options) {
this.body = body
this.type = 'default'
this.url = null
this.status = options.status
this.statusText = options.statusText
this.headers = options.headers
}
Body.call(Response.prototype)
window.fetch = function (url, options) {
return new Request(url, options).fetch()
}
})()