Javascript call function after multiple XMLHttpRequests - javascript

I have some divs that I replace with new html. So far so good.
(function() {
var obj = function(div) {
var obj = {};
obj.divToReplace = div;
obj.objId = obj.divToReplace.dataset.id;
obj.template = "<div class="newDivs"><p>#Name</p><img src='#ImageUrl'/></div>";
obj.replaceDiv = function() {
var xhr = new XMLHttpRequest();
xhr.open( 'GET', encodeURI('http://.../' + obj.objId) );
xhr.onload = function(e) {
if (xhr.status === 200) {
var x = JSON.parse(xhr.responseText).data.attributes;
var newHtml = obj.template
.replaceAll("#Name", x.name)
.replaceAll("#ImageUrl", x.imageUrl);
obj.divToReplace.outerHTML = newHtml;
}
else {
console.log(xhr.status);
}
};
xhr.send();
};
return {
replaceDiv: obj.replaceDiv
}
};
String.prototype.replaceAll = function(search, replace)
{
return this.replace(new RegExp(search, 'g'), replace);
};
//get the elements I want to replace
var elems = document.getElementsByClassName('divToReplace');
//replace them
for (i = 0; i < elems.length; i++) {
obj(elems[i]).replaceDiv();
}
//call handleStuff ?
})();
Then I want to add addEventListener to the divs, and it's here I get stuck. I want to call handleStuff() after all the divs are replaced. (Because of course, before I replace them the new divs don't exists.) And I can't use jQuery.
var handleStuff = function(){
var classname = document.getElementsByClassName("newDivs");
var myFunction = function() {
};
for (var i = 0; i < classname.length; i++) {
classname[i].addEventListener('click', myFunction, false);
}
...............
How can I add a callback that tells me when all the divs are replaced? Or is it overall not a good solution for what I'm trying to do?

Sorry for using jQuery previously, here is solution with native Promise(tested)
(function() {
var f = {
send : function(){
var promise = new Promise(function(resolve, reject){
var xhr = new XMLHttpRequest();
xhr.open( 'GET', encodeURI('http://www.google.com/') );
xhr.onload = function(e) {
if (xhr.status === 200) {
//your code
resolve();
console.log('resolve');
} else {
console.log(xhr.status);
}
};
xhr.send();
});
return promise;
}
}
var promises = [];
for (i = 0; i < 100; i++) {
promises.push(f.send());
}
Promise.all(promises).then(function(){
console.log('success');
});
})();

Related

How to dynamically load photos to dynamically loaded divs?

I wrote this code, which creates divs depending on the amount of text files in local directory.
Then I tried to write additional code, which appends photos to each of these divs. Unfortunately, this code doesn't append any photos...
function liGenerator() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
var n = (xmlhttp.responseText.match(/txt/g) || []).length;
for (var i = 1; i < n; i++) {
$.get("projects/txt/"+i+".txt", function(data) {
var line = data.split('\n');
var num = line[0]-"\n";
var clss = line[1];
var title = line[2];
var price = line[3];
var content = line[4];
$("#list-portfolio").append("<li class='item "+clss+" show' onclick='productSelection('"+num+"')'><img src='projects/src/"+num+"/title.jpg'/><div class='title'><h1>"+title+"</h1><h2>"+price+"</h2></div><article>"+content+"</article></li>");
$("#full-size-articles").append("<li class='product "+num+"'><div><div class='photo_gallery'><div id='fsa_img "+num+"'><div width='100%' class='firstgalleryitem'></div></div></div><article class='content'><h1 class='header_article'>"+title+"</h1><h2 class='price_article'>"+price+"</h2><section class='section_article'>"+content+"</section></article></div></li>");
});
}
}
}
};
xmlhttp.open("GET", "projects/txt/", true);
xmlhttp.send();
}
function pushPhotos() {
var list = document.getElementById("full-size-articles").getElementsByTagName("li");
var amount = list.length;
for(var i=1;i<=amount;i++) {
var divID = "#fsa_img "+i;
var where = "projects/src/"+i+"/";
var fx = ".jpg";
loadPhotos(where, fx, divID);
}
}
function loadPhotos(dir, fileextension, div) {
$.ajax({
url: dir,
success: function (data) {
$(data).find("a:contains(" + fileextension + ")").each(function () {
var filename = this.href.replace(window.location, "").replace("http://", "");
$(div).append("<img src='"+dir+filename+"' class='mini_photo'/>");
});
}
});
}
Any ideas on why this code is not working as intended?
The main issue is the space between "#fsa_img" and "i". When I changed it to '"#fsa_img_"+i', the code started work as intended.

html table no longer supported

As others before I used yql to get data from a website. The website is in xml format.
I am doing this to build a web data connector in Tableau to connect to xmldata and I got my code from here: https://github.com/tableau/webdataconnector/blob/v1.1.0/Examples/xmlConnector.html
As recommended on here: YQL: html table is no longer supported I tried htmlstring and added the reference to the community environment.
// try to use yql as a proxy
function _yqlProxyAjaxRequest2(url, successCallback){
var yqlQueryBase = "http://query.yahooapis.com/v1/public/yql?q=";
var query = "select * from htmlstring where url='" + url + "'";
var restOfQueryString = "&format=xml" ;
var yqlUrl = yqlQueryBase + encodeURIComponent(query) + restOfQueryString + "&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";
_ajaxRequestHelper(url, successCallback, yqlUrl, _giveUpOnUrl9);
}
function _giveUpOnUrl9(url, successCallback) {
tableau.abortWithError("Could not load url: " + url);
}
However, I still got the message: Html table no longer supported.
As I don't know much about yql, I tried to work with xmlHttpRequestinstead, but Tableau ended up processing the request for ages and nothing happened.
Here my attempt to find another solution and avoid the yql thingy:
function _retrieveXmlData(retrieveDataCallback) {
if (!window.cachedTableData) {
var conData = JSON.parse(tableau.connectionData);
var xmlString = conData.xmlString;
if (conData.xmlUrl) {
var successCallback = function(data) {
window.cachedTableData = _xmlToTable(data);
retrieveDataCallback(window.cachedTableData);
};
//INSTEAD OF THIS:
//_basicAjaxRequest1(conData.xmlUrl, successCallback);
//USE NOT YQL BUT XMLHTTPREQUEST:
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
myFunction(this);
}
};
xhttp.open('GET', 'https://www.w3schools.com/xml/cd_catalog.xml', true);
xhttp.send();
return;
}
try {
var xmlDoc = $.parseXML(conData.xmlString);
window.cachedTableData = _xmlToTable(xmlDoc);
}
catch (e) {
tableau.abortWithError("unable to parse xml data");
return;
}
}
retrieveDataCallback(window.cachedTableData);
}
Does anyone have an idea how to get YQL work or comment on my approach trying to avoid it?
Thank you very much!
For reference, if there is any Tableau user that wants to test it on Tableau, here is my full code:
<html>
<head>
<title>XML Connector</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" type="text/javascript"></script>
<script src="https://connectors.tableau.com/libs/tableauwdc-1.1.1.js" type="text/javascript"></script>
<script type="text/javascript">
(function() {
var myConnector = tableau.makeConnector();
myConnector.init = function () {
tableau.connectionName = 'XML data';
tableau.initCallback();
};
myConnector.getColumnHeaders = function() {
_retrieveXmlData(function (tableData) {
var headers = tableData.headers;
var fieldNames = [];
var fieldTypes = [];
for (var fieldName in headers) {
if (headers.hasOwnProperty(fieldName)) {
fieldNames.push(fieldName);
fieldTypes.push(headers[fieldName]);
}
}
tableau.headersCallback(fieldNames, fieldTypes); // tell tableau about the fields and their types
});
}
myConnector.getTableData = function (lastRecordToken) {
_retrieveXmlData(function (tableData) {
var rowData = tableData.rowData;
tableau.dataCallback(rowData, rowData.length.toString(), false);
});
};
tableau.registerConnector(myConnector);
})();
function _retrieveXmlData(retrieveDataCallback) {
if (!window.cachedTableData) {
var conData = JSON.parse(tableau.connectionData);
var xmlString = conData.xmlString;
if (conData.xmlUrl) {
var successCallback = function(data) {
window.cachedTableData = _xmlToTable(data);
retrieveDataCallback(window.cachedTableData);
};
//_basicAjaxRequest1(conData.xmlUrl, successCallback);
//here try another approach not using yql but xmlHttpRequest?
//try xml dom to get url (xml http request)
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
myFunction(this);
}
};
xhttp.open('GET', 'https://www.w3schools.com/xml/cd_catalog.xml', true);
xhttp.send();
return;
}
try {
var xmlDoc = $.parseXML(conData.xmlString);
window.cachedTableData = _xmlToTable(xmlDoc);
}
catch (e) {
tableau.abortWithError("unable to parse xml data");
return;
}
}
retrieveDataCallback(window.cachedTableData);
}
function myFunction(xml) {
var xmlDoc = xml.responseXML;
window.cachedTableData = _xmlToTable(xmlDoc);
}
// There are a lot of ways to handle URLS. Sometimes we'll need workarounds for CORS. These
// methods chain together a series of attempts to get the data at the given url
function _ajaxRequestHelper(url, successCallback, conUrl, nextFunction,
specialSuccessCallback){
specialSuccessCallback = specialSuccessCallback || successCallback;
var xhr = $.ajax({
url: conUrl,
dataType: 'xml',
success: specialSuccessCallback,
error: function()
{
nextFunction(url, successCallback);
}
});
}
// try the straightforward request
function _basicAjaxRequest1(url, successCallback){
_ajaxRequestHelper(url, successCallback, url, _yqlProxyAjaxRequest2);
}
// try to use yql as a proxy
function _yqlProxyAjaxRequest2(url, successCallback){
var yqlQueryBase = "http://query.yahooapis.com/v1/public/yql?q=";
var query = "select * from htmlstring where url='" + url + "'";
var restOfQueryString = "&format=xml" ;
var yqlUrl = yqlQueryBase + encodeURIComponent(query) + restOfQueryString + "&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";
_ajaxRequestHelper(url, successCallback, yqlUrl, _giveUpOnUrl9);
}
function _giveUpOnUrl9(url, successCallback) {
tableau.abortWithError("Could not load url: " + url);
}
// Takes a hierarchical xml document and tries to turn it into a table
// Returns an object with headers and the row level data
function _xmlToTable(xmlDocument) {
var rowData = _flattenData(xmlDocument);
var headers = _extractHeaders(rowData);
return {"headers":headers, "rowData":rowData};
}
// Given an object:
// - finds the longest array in the xml
// - flattens each element in that array so it is a single element with many properties
// If there is no array that is a descendent of the original object, this wraps
function _flattenData(xmlDocument) {
// first find the longest array
var longestArray = _findLongestArray(xmlDocument, xmlDocument);
if (!longestArray || longestArray.length == 0) {
// if no array found, just wrap the entire object blob in an array
longestArray = [objectBlob];
}
toRet = [];
for (var ii = 0; ii < longestArray.childNodes.length; ++ii) {
toRet[ii] = _flattenObject(longestArray.childNodes[ii]);
}
return toRet;
}
// Given an element with hierarchical properties, flattens it so all the properties
// sit on the base element.
function _flattenObject(xmlElt) {
var toRet = {};
if (xmlElt.attributes) {
for (var attributeNum = 0; attributeNum < xmlElt.attributes.length; ++attributeNum) {
var attribute = xmlElt.attributes[attributeNum];
toRet[attribute.nodeName] = attribute.nodeValue;
}
}
var children = xmlElt.childNodes;
if (!children || !children.length) {
if (xmlElt.textContent) {
toRet.text = xmlElt.textContent.trim();
}
} else {
for (var childNum = 0; childNum < children.length; ++childNum) {
var child = xmlElt.childNodes[childNum];
var childName = child.nodeName;
var subObj = _flattenObject(child);
for (var k in subObj) {
if (subObj.hasOwnProperty(k)) {
toRet[childName + '_' + k] = subObj[k];
}
}
}
}
return toRet;
}
// Finds the longest array that is a descendent of the given object
function _findLongestArray(xmlElement, bestSoFar) {
var children = xmlElement.childNodes;
if (children && children.length) {
if (children.length > bestSoFar.childNodes.length) {
bestSoFar = xmlElement;
}
for (var childNum in children) {
var subBest = _findLongestArray(children[childNum], bestSoFar);
if (subBest.childNodes.length > bestSoFar.childNodes.length) {
bestSoFar = subBest;
}
}
}
return bestSoFar;
}
// Given an array of js objects, returns a map from data column name to data type
function _extractHeaders(rowData) {
var toRet = {};
for (var row = 0; row < rowData.length; ++row) {
var rowLine = rowData[row];
for (var key in rowLine) {
if (rowLine.hasOwnProperty(key)) {
if (!(key in toRet)) {
toRet[key] = _determineType(rowLine[key]);
}
}
}
}
return toRet;
}
// Given a primitive, tries to make a guess at the data type of the input
function _determineType(primitive) {
// possible types: 'float', 'date', 'datetime', 'bool', 'string', 'int'
if (parseInt(primitive) == primitive) return 'int';
if (parseFloat(primitive) == primitive) return 'float';
if (isFinite(new Date(primitive).getTime())) return 'datetime';
return 'string';
}
function _submitXMLToTableau(xmlString, xmlUrl) {
var conData = {"xmlString" : xmlString, "xmlUrl": xmlUrl};
tableau.connectionData = JSON.stringify(conData);
tableau.submit();
}
function _buildConnectionUrl(url) {
// var yqlQueryBase = "http://query.yahooapis.com/v1/public/yql?q=";
// var query = "select * from html where url='" + url + "'";
// var restOfQueryString = "&format=xml";
// var yqlUrl = yqlQueryBase + encodeURIComponent(query) + restOfQueryString;
// return yqlUrl;
return url;
}
$(document).ready(function(){
var cancel = function (e) {
e.stopPropagation();
e.preventDefault();
}
$("#inputForm").submit(function(e) { // This event fires when a button is clicked
// Since we use a form for input, make sure to stop the default form behavior
cancel(e);
var xmlString = $('textarea[name=xmlText]')[0].value.trim();
var xmlUrl = $('input[name=xmlUrl]')[0].value.trim();
_submitXMLToTableau(xmlString, xmlUrl);
});
var ddHandler = $("#dragandrophandler");
ddHandler.on('dragenter', function (e)
{
cancel(e);
$(this).css('border', '2px solid #0B85A1');
}).on('dragover', cancel)
.on('drop', function (e)
{
$(this).css('border', '2px dashed #0B85A1');
e.preventDefault();
var files = e.originalEvent.dataTransfer.files;
var file = files[0];
var reader = new FileReader();
reader.onload = function(e) { _submitXMLToTableau(reader.result); };
reader.readAsText(file);
});
$(document).on('dragenter', cancel)
.on('drop', cancel)
.on('dragover', function (e)
{
cancel(e);
ddHandler.css('border', '2px dashed #0B85A1');
});
});
</script>
<style>
#dragandrophandler {
border:1px dashed #999;
width:300px;
color:#333;
text-align:left;vertical-align:middle;
padding:10px 10px 10 10px;
margin:10px;
font-size:150%;
}
</style>
</head>
<body>
<form id="inputForm" action="">
Enter a URL for XML data:
<input type="text" name="xmlUrl" size="50" />
<br>
<div id="dragandrophandler">Or Drag & Drop Files Here</div>
<br>
Or paste XML data below
<br>
<textarea name="xmlText" rows="10" cols="70"/></textarea>
<input type="submit" value="Submit">
</form>

(beginner javascript) get multiple text files xml request

Very grateful if someone can help me out with the syntax here- I am hoping to make several XML requests, each time getting a different text file. Here is the general structure of my code. How can I get each file in turn (f0, f1 and f2)?
window.onload = function(){
var f = (function(){
var xhr = [];
for (i = 0; i < 3; i++){
(function (i){
xhr[i] = new XMLHttpRequest();
f0 = "0.txt"
f1 = "1.txt"
f2 = "2.txt"
//??? xhr[i].open("GET", file i, true);
xhr[i].onreadystatechange = function () {
if (xhr[i].readyState == 4 && xhr[i].status == 200) {
//do stuff
}
};
xhr[i].send();
})(i);
}
})();
};
Simply put your filenames in an array.
window.onload = function(){
var f = (function(){
var xhr = [];
var files = ["f0.txt", "f1.txt", "f2.txt"];
for (i = 0; i < 3; i++){
(function (i){
xhr[i] = new XMLHttpRequest();
xhr[i].open("GET", files[i], true);
xhr[i].onreadystatechange = function () {
if (xhr[i].readyState == 4 && xhr[i].status == 200) {
//do stuff
}
};
xhr[i].send();
})(i);
}
})();
};
Something like this should work
// ...
for (i = 0; i < 3; i++){
(function (i){
xhr[i] = new XMLHttpRequest();
xhr[i].open('GET', i.toString() + '.txt'); // <-- this line
xhr[i].onreadystatechange = function () {
if (xhr[i].readyState == 4 && xhr[i].status == 200) {
// ....

Uncaught TypeError: Object #<AbstractAjaxReq> has no method 'getAjaxResponse'

I want to implement some good OOP practices into my javascript somehow. As you can see I am having an abstractAjaxRequest and then giving it some children that define its getAjaxResponse function. I get the error posted at the bottom, on this line: self.getAjaxResponse(). Anyone see the error of my ways?
function soapReq() {
var ajaxRequest = new SignInAjaxReq();
ajaxRequest.init();
var SOAPRequest = getSOAPHead();
var bodyArgs = getLoginAttempt();
SOAPRequest += getSOAPBody(bodyArgs[0], bodyArgs[1], bodyArgs[2]);
SOAPRequest += getSOAPFoot();
var url = 'xxx'
ajaxRequest.ajaxRequest.open('POST', url, true);
ajaxRequest.ajaxRequest.setRequestHeader( "Content-Type","text/xml; charset=utf-8");
ajaxRequest.ajaxRequest.send(SOAPRequest);
}
function AbstractAjaxReq() {
var self = this;
this.init = function() {
self.ajaxRequest = new XMLHttpRequest();
self.ajaxRequest.onreadystatechange = function() {
if(self.ajaxRequest.readyState === 4){
self.getAjaxResponse() // error here
}
};
return self.ajaxRequest;
};
};
function SignInAjaxReq() {
var self = this;
this.getAjaxResponse = function() {
var xml = self.ajaxRequest.responseXML;
var x=xml.getElementsByTagName("signInResult");
for (i=0;i<x.length;i++) {
console.log(x[i].childNodes[0].nodeValue);
}
};
};
SignInAjaxReq.prototype = new AbstractAjaxReq();
Uncaught TypeError: Object #<AbstractAjaxReq> has no method 'getAjaxResponse' SoapRequest.js:42
self.ajaxRequest.onreadystatechange
Your inheritance is flawed. When you create the prototype by new AbstractReq(), then the self closure variable will point to that prototype object - which does not have a getAjaxResponse method.
Fix #1: Use correct inheritance:
function AbstractAjaxReq() {
var self = this;
this.init = function() {
self.ajaxRequest = new XMLHttpRequest();
self.ajaxRequest.onreadystatechange = function() {
if(self.ajaxRequest.readyState === 4){
self.getAjaxResponse() // no more error here
}
};
return self.ajaxRequest;
};
};
function SignInAjaxReq() {
AbstractAjaxReq.call(this); // invoke the super constructor
var self = this;
this.getAjaxResponse = function() {
var xml = self.ajaxRequest.responseXML;
var x=xml.getElementsByTagName("signInResult");
for (i=0;i<x.length;i++) {
console.log(x[i].childNodes[0].nodeValue);
}
};
};
SignInAjaxReq.prototype = Object.create(AbstractAjaxReq.prototype);
Fix #2: Assign the actual instance to self by creating the variable in the init function:
function AbstractAjaxReq() {
this.init = function() {
var self = this; // here!
self.ajaxRequest = new XMLHttpRequest();
self.ajaxRequest.onreadystatechange = function() {
if(self.ajaxRequest.readyState === 4){
self.getAjaxResponse() // no more error here
}
};
return self.ajaxRequest;
};
};
Also, use the prototype! Example:
var abstractAjaxPrototype = {
init: function() {
var self = this; // here!
this.ajaxRequest = new XMLHttpRequest();
this.ajaxRequest.onreadystatechange = function() {
if (self.ajaxRequest.readyState === 4){
self.getAjaxResponse() // no more error here
}
};
return this.ajaxRequest;
}
};
function SignInAjaxReq() { }
SignInAjaxReq.prototype = Object.create(abstractAjaxPrototype);
SignInAjaxReq.prototype.getAjaxResponse = function() {
var xml = this.ajaxRequest.responseXML;
var x = xml.getElementsByTagName("signInResult");
for (i=0; i<x.length; i++) {
console.log(x[i].childNodes[0].nodeValue);
}
};
And: don't use init methods, use the constructor:
function AbstractAjaxReq() {
var self = this; // here!
self.ajaxRequest = new XMLHttpRequest();
self.ajaxRequest.onreadystatechange = function() {
if(self.ajaxRequest.readyState === 4){
self.getAjaxResponse() // no more error here
}
};
};
function SignInAjaxReq() {
AbstractAjaxReq.call(this); // invoke the super constructor
}
SignInAjaxReq.prototype = Object.create(abstractAjaxPrototype);
SignInAjaxReq.prototype.getAjaxResponse = function() {
var xml = this.ajaxRequest.responseXML;
var x = xml.getElementsByTagName("signInResult");
for (i=0; i<x.length; i++) {
console.log(x[i].childNodes[0].nodeValue);
}
};
// Usage:
var ajaxRequest = new SignInAjaxReq();
// no ajaxRequest.init()!

Downloading binary data using XMLHttpRequest, without overrideMimeType

I am trying to retrieve the data of an image in Javascript using XMLHttpRequest.
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://www.celticfc.net/images/doc/celticcrest.png");
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
var resp = xhr.responseText;
console.log(resp.charCodeAt(0) & 0xff);
}
};
xhr.send();
The first byte of this data should be 0x89, however any high-value bytes return as 0xfffd (0xfffd & 0xff being 0xfd).
Questions such as this one offer solutions using the overrideMimeType() function, however this is not supported on the platform I am using (Qt/QML).
How can I download the data correctly?
Google I/O 2011: HTML5 Showcase for Web Developers: The Wow and the How
Fetch binary file: new hotness
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.celticfc.net/images/doc/celticcrest.png', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
if (this.status == 200) {
var uInt8Array = new Uint8Array(this.response); // Note:not xhr.responseText
for (var i = 0, len = uInt8Array.length; i < len; ++i) {
uInt8Array[i] = this.response[i];
}
var byte3 = uInt8Array[4]; // byte at offset 4
}
}
xhr.send();
I'm not familiarized with Qt but i found this in their documentation
string Qt::btoa ( data )
Binary to ASCII - this function returns a base64 encoding of data.
So, if your image is a png you can try:
resp = "data:image/png;base64," + btoa(resp);
document.write("<img src=\""+resp+"\">");
Qt version 5.13.1(support native Promise in qml env), prue qml.
function fetch, like node-fetch
function hexdump, dump the data as hex, just use the linux command hexdump to check.
function createResponse(xhr) {
let res = {};
function headersParser() {
let headersRaw = {};
let lowerCaseHeaders = {};
let rawHeaderArray = xhr.getAllResponseHeaders().split("\n");
for(let i in rawHeaderArray) {
let rawHeader = rawHeaderArray[i];
let headerItem = rawHeader.split(":");
let name = headerItem[0].trim();
let value = headerItem[1].trim();
let lowerName = name.toLowerCase();
headersRaw[name] = value;
lowerCaseHeaders [lowerName] = value;
}
return {
"headersRaw": headersRaw,
"lowerCaseHeaders": lowerCaseHeaders
};
}
res.headers = {
__alreayParse : false,
raw: function() {
if (!res.headers.__alreayParse) {
let {headersRaw, lowerCaseHeaders} = headersParser();
res.headers.__alreayParse = true;
res.headers.__headersRaw = headersRaw;
res.headers.__lowerCaseHeaders = lowerCaseHeaders;
}
return res.headers.__headersRaw;
},
get: function(headerName) {
if (!res.headers.__alreayParse) {
let {headersRaw, lowerCaseHeaders} = headersParser();
res.headers.__alreayParse = true;
res.headers.__headersRaw = headersRaw;
res.headers.__lowerCaseHeaders = lowerCaseHeaders;
}
return res.headers.__lowerCaseHeaders[headerName.toLowerCase()];
}
};
res.json = function() {
if(res.__json) {
return res.__json;
}
return res.__json = JSON.parse(xhr.responseText);
}
res.text = function() {
if (res.__text) {
return res.__text;
}
return res.__text = xhr.responseText;
}
res.arrayBuffer = function() {
if (res.__arrayBuffer) {
return res.__arrayBuffer;
}
return res.__arrayBuffer = new Uint8Array(xhr.response);
}
res.ok = (xhr.status >= 200 && xhr.status < 300);
res.status = xhr.status;
res.statusText = xhr.statusText;
return res;
}
function fetch(url, options) {
return new Promise(function(resolve, reject) {
let requestUrl = "";
let method = "";
let headers = {};
let body;
let timeout;
if (typeof url === 'string') {
requestUrl = url;
method = "GET";
if (options) {
requestUrl = options['url'];
method = options['method'];
headers = options['headers'];
body = options['body'];
timeout = options['timeout'];
}
} else {
let optionsObj = url;
requestUrl = optionsObj['url'];
method = optionsObj['method'];
headers = optionsObj['headers'];
body = optionsObj['body'];
timeout = optionsObj['timeout'];
}
let xhr = new XMLHttpRequest;
if (timeout) {
xhr.timeout = timeout;
}
// must set responseType to arraybuffer, then the xhr.response type will be ArrayBuffer
// but responseType not effect the responseText
xhr.responseType = 'arraybuffer';
xhr.onreadystatechange = function() {
// readyState as follow: UNSENT, OPENED, HEADERS_RECEIVED, LOADING, DONE
if(xhr.readyState === XMLHttpRequest.DONE) {
resolve(createResponse(xhr));
}
};
xhr.open(method, requestUrl);
// todo check headers
for(var iter in headers) {
xhr.setRequestHeader(iter, headers[iter]);
}
if("GET" === method || "HEAD" === method) {
xhr.send();
} else {
xhr.send(body);
}
});
}
function hexdump(uint8array) {
let count = 0;
let line = "";
let lineCount = 0;
let content = "";
for(let i=0; i<uint8array.byteLength; i++) {
let c = uint8array[i];
let hex = c.toString(16).padStart (2, "0");
line += hex + " ";
count++;
if (count === 16) {
let lineCountHex = (lineCount).toString (16).padStart (7, "0") + "0";
content += lineCountHex + " " + line + "\n";
line = "";
count = 0;
lineCount++;
}
}
if(line) {
let lineCountHex = (lineCount).toString (16).padStart (7, "0") + "0";
content += lineCountHex + " " + line + "\n";
line = "";
// count = 0;
lineCount++;
}
content+= (lineCount).toString (16).padStart (7, "0") + count.toString(16) +"\n";
return content;
}
fetch("https://avatars2.githubusercontent.com/u/6630355")
.then((res)=>{
try {
let headers = res.headers.raw();
console.info(`headers:`, JSON.stringify(headers));
let uint8array = res.arrayBuffer();
let hex = hexdump(uint8array);
console.info(hex)
}catch(error) {
console.trace(error);
}
})
.catch((error)=>{
});

Categories

Resources