I want to convert a jquery function into a javascript function:
window.parent.$.ajax({
type: 'GET',
url: "http://localhost:3063/corsService/GetCultureInformation",
contentType: "application/json",
dataType: "json",
success: function (data) {
numberDecimalDigit = data.NumberDecimalDigits;
},
async: false
});
I converted it to:
var request = new XMLHttpRequest();
request.open('GET', 'http://localhost:3063/corsService/GetCultureInformation', false);
request.onload = function() {
if (this.status >= 200 && this.status < 400) {
// Success!
numberDecimalDigit = data.NumberDecimalDigits;
var resp = this.response;
} else {
// We reached our target server, but it returned an error
}
};
request.onerror = function() {
// There was a connection error of some sort
};
request.send();
but I have errors:
1: XMLHttpRequest: Network Error 0x2efd, Could not complete the operation due to error 00002efd.
2: NetworkError
//Better use promises, as it reduces biolerplate heavy code of XMLhttp request provides.
function loadjson(file) {
return new Promise((resolve, reject) => {
return fetch(file).then((response) => {
if (response.ok) {
resolve(response.json());
} else {
reject(new Error("error"));
}
});
});
}
var newFile=loadjson("https://api.postalpincode.in/pincode/110001").then((data) => {
console.log(data);
});
Related
I have this script that I use to import some data from an API, and into my database. Since this process is very time consuming, it often times out because on some of the items processed there is a lot of data to process..
I came with this solution a while ago, using promises, to first do the request to the API, then after it finishes I would prepare the data and put it into a temporary csv file, then I would fire another request to split that file into multiple smaller files, then... you get the idea... it was working, but I need to add to it some extra requests, I just can't make it work... I probably just need to simplify my logic.
Anyone can help me improve this code to make it easier to add those extra requests and keep it sending one request after the other?
This is the (over simplified) script in question:
window.importTrialsScripts = {};
window.addEventListener('DOMContentLoaded', function() {
importTrialsScripts.app.initialize();
});
(function(importTrialsScripts, document, $) {
importTrialsScripts = importTrialsScripts || {};
const app = {
ajaxurl: 'myajaxurl',
initialize: function() {
this.submitHandler();
},
submitHandler: function() {
const self = this;
document.querySelector('#start-import').addEventListener('click', function() {
self.pullTrialsFromApi();
});
},
pullTrialsFromApi: function() {
let data = new FormData();
data.append('action', 'pull_trials_from_api');
[123, 456, 789].forEach(function(str) {
data.append('ids[]', str);
});
this.startPullingTrials(data);
},
startPullingTrials: function(data) {
const self = this;
let promise = new Promise(function(resolve, reject) {
self.sendAjaxRequest(data, function() {
if (this.status === 200) {
const response = JSON.parse(this.response);
if (! response.success) {
alert('The API could not be reached. Please try again.');
console.error('Error!!', response);
return;
}
resolve(response.data);
}
else {
console.error('there was an error in the request', this);
reject(this);
}
});
});
promise.then(function(chunks) {
const processingChunks = Object.values(chunks).map(function(chunk) {
return self.processChunk(chunk);
});
Promise.all(processingChunks).then(function (processedTrials) {
console.log('finished', processedTrials);
});
}, function(err) {
console.error('promise rejected', err);
});
},
processChunk: function(chunkTrials) {
const self = this;
let data = new FormData();
data.append('action', 'process_trials_chunk');
Object.values(chunkTrials).forEach(function(chunk) {
data.append('chunk[]', JSON.stringify(chunk));
});
return new Promise(function(resolve, reject) {
self.sendAjaxRequest(data, function() {
if (this.status === 200) {
const response = JSON.parse(this.response);
if (! response.success) {
console.error('Error!!', response.data);
return;
}
resolve(response.data);
}
else {
console.log('there was an error in the request', this);
reject(this);
}
});
});
},
splitToMultipleFiles: function() {
const self = this;
const data = new FormData();
data.append('action', 'split_location_files');
return new Promise(function(resolve, reject) {
self.sendAjaxRequest(data, function() {
if (this.status === 200) {
const response = JSON.parse(this.response);
if ( ! response.success ) {
console.error('Error!!', response.data);
return;
}
resolve(response.data.files);
}
else {
console.log('there was an error in the request', this);
reject(this);
}
});
});
},
processLocation: function(file) {
const self = this;
let data = new FormData();
data.append('action', 'process_location_data');
data.append('file', file);
return new Promise(function(resolve, reject) {
self.sendAjaxRequest(data, function() {
if ( this.status === 200 ) {
const response = JSON.parse(this.response);
if (! response.success) {
console.error('Error!!', response.data);
return;
}
resolve(response.data);
}
else {
console.log('there was an error in the request', this);
reject(this);
}
});
});
},
sendAjaxRequest: function(data, callback) {
const self = this;
let xhr = new XMLHttpRequest();
xhr.open('POST', ajaxurl);
xhr.onload = callback;
xhr.addEventListener('timeout', function(e) {
console.error('the request has timed out', e);
});
xhr.addEventListener('error', function(e) {
console.error('the request returned an error', e);
});
xhr.addEventListener('abort', function(e) {
console.error('the request was aborted', e);
});
xhr.send(data);
},
};
$.extend(importTrialsScripts, {
app: app
});
}).apply(this, [window.importTrialsScripts, document, jQuery]);
With manifest v2, I used URL.createObjectURL in order to return file from background to content. How do this with manifest v3 and Service Worker? I know about XMLHttpRequest to fetch. But what analog URL.createObjectURL?
// background.js
function onContentMessage(message, sender, sendResponse) {
if (message.action == 'requestFileGET') {
requestFileGET(message.url, (url) => sendResponse(url));
}
return true;
}
function requestFileGET(url, callback) {
let request = new XMLHttpRequest();
request.responseType = 'blob';
request.onreadystatechange = function () {
if (request.readyState == 4) {
let url = URL.createObjectURL(request.response);
callback(url);
}
};
request.open('GET', url);
request.send();
}
// content.js
backgroundFileGET(urlCover, (cover) => {
let url = `${HANDLER_UPLOADPIC}?kind=${kind}&sign=${sign}`;
let formData = new FormData();
formData.append('file', cover);
requestFilePOST(url, formData, callback);
});
function backgroundFileGET(url, callback) {
backgroundRequest('requestFileGET', url, (backgroungdUrl) => {
requestFileGET(backgroungdUrl, (file) => callback(file));
});
}
function backgroundRequest(action, url, callback) {
chrome.runtime.sendMessage({ action: action, url: url }, (response) => callback(response));
}
My Solution Store the data with a ID and open a new tab with a page like download.html#ID
let videoId = '#' + new Date().valueOf();
self.DownloadedVideoData[videoId] = { data: data, filename:
filename, mimetype:mimetype, segment:segment, action:'download' };
chrome.tabs.create({ url: "video.html" + videoId, active: false });
Inside the Page register a function to onload and your downloading Code
chrome.runtime.sendMessage({
action: 'GetVideoDataByID',
VideoID: self.VideoID,
}, function (videoData) {
if (videoData.action == 'download') self.DownloadVideo(videoData);
);
self.DownloadVideo = function (request) {
let blob = new Blob(request.data, { type: request.mimetype }),
downloadId;
chrome.downloads.onChanged.addListener(function (dl) {
if (dl.id === downloadId && dl.state && dl.state.current ==
'complete') {
window.close();
}
});
chrome.downloads.download({
url: URL.createObjectURL(blob),
filename: request.filename
}, function (id) {
downloadId = id;
window.close();
});
}
Now you need only a Listener in your Backround Worker like that
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
switch (request.action) {
case 'GetVideoDataByID':
sendResponse(self.GetVideoDataByID(request.VideoID));
break;
default:
break;
}
}
I'm trying to rerun a failed AJAX call 3 times. After the third attempt, I'd like to call a failed method. I don't want the AJAX calls to over run each other though.
What's the safest/best way to achieve this with what I'm working with?
I'm using a globalAjaxRequest method like so:
globalAjaxRequest(request, successCallback, errorCallback) {
let ajaxRequest = null;
if (request.url) {
const ajaxOptions = {
type: request.method ? request.method.toUpperCase() : 'POST',
url: request.url,
data: request.data || undefined,
beforeSend: request.beforeSend,
success: (data) => {
successCallback(data);
},
error: (data) => {
if (errorCallback) {
errorCallback(data);
}
}
};
ajaxOptions.dataType = request.dataType || 'json';
ajaxOptions.contentType = request.contentType || 'application/json; charset=utf-8';
if (request.contentType) {
ajaxOptions.data = $.parseJSON(JSON.stringify(ajaxOptions.data));
} else {
ajaxOptions.data = JSON.stringify(ajaxOptions.data);
}
ajaxRequest = $.ajax(ajaxOptions);
}
return ajaxRequest;
}
}
Here's my attempt:
callAPI() {
const callData = {
url: '/callApi',
data: {
id: 'something'
}
};
global.Utils.globalAjaxRequest(callData, (success) => {
console.log('success');
successMethod();
}, (fail) => {
for (let i = 1;; i++) {
i <= 3 && setTimeout(() => {
callAPI();
}, 1000);
if (i > 3) {
failedMethod();
break;
}
}
});
}
callAPI();
You can't retry an asynchronous operation such as $.ajax() synchronously, so I'll assume that you just meant you want to automatically retry sequentially if it fails.
Here's a generic retry function for $.ajax():
// general purpose promise delay, useful when you want to delay a promise chain
function pDelay(t, v) {
return new Promise(function(resolve) {
setTimeout(resolve, t, v);
});
}
// three arguments:
// options: value for $.ajax(options) - does not support other forms of calling $.ajax()
// delay: amount of time in ms to delay before each retry (can be 0 if you want)
// retries: number of times to retry, defaults to 3 if you don't pass it
$.ajaxRetry = function(options, delay, retries) {
// default value for retries is 3 if the argument is not passed
let retriesRemaining = retriesRemaining !== undefined ? retriesRemaining: 3;
let opts = Object.assign({}, options);
function run() {
return $.ajax(opts).catch(function(err) {
--retriesRemaining;
// don't fire this more than once
delete opts.beforeSend;
if (retriesRemaining > 0) {
// try again after short delay
return pDelay(delay).then(run);
} else {
// hit max retries, propagate error back to caller
throw e;
}
});
}
return run();
}
FYI, this code assumes that "failure" in your case means that the promise that $.ajax() rejects. If "failure" means something else (such as looking at some result you got), then you will have to insert that additional test into the retry loop or expose a callback where that additional test can be provided externally.
To integrate this into your wrapper, you could do this:
globalAjaxRequest(request, successCallback, errorCallback) {
let ajaxRequest = null;
if (request.url) {
const ajaxOptions = {
type: request.method ? request.method.toUpperCase() : 'POST',
url: request.url,
data: request.data || undefined,
beforeSend: request.beforeSend,
};
ajaxOptions.dataType = request.dataType || 'json';
ajaxOptions.contentType = request.contentType || 'application/json; charset=utf-8';
if (request.contentType) {
ajaxOptions.data = $.parseJSON(JSON.stringify(ajaxOptions.data));
} else {
ajaxOptions.data = JSON.stringify(ajaxOptions.data);
}
errorCallback = errorCallback || function(err) { throw err; };
ajaxRequest = $.ajaxRetry(ajaxOptions, 0, 3).then(successCallback, errorCallback);
}
return ajaxRequest;
}
}
FYI, it is kind of odd to take a promise interface and turn it back into plain callbacks. It seems you should just get rid of successCallback and errorCallback let the caller use the returned promise.
I'd do something like this that uses a closure to keep a counter above the async request:
globalAjaxRequest(request, successCallback, errorCallback, maxRequests) {
maxRequests = maxRequests || 1;
var requests = 1;
function ajaxRequest(request){
if (request.url) {
const ajaxOptions = {
type: request.method ? request.method.toUpperCase() : 'POST',
url: request.url,
data: request.data || undefined,
beforeSend: request.beforeSend,
success: (data) => {
successCallback(data);
},
error: (data) => {
if (requests < maxRequests){
requests++;
ajaxRequest(request);
} else if (errorCallback) {
errorCallback(data);
}
}
};
ajaxOptions.dataType = request.dataType || 'json';
ajaxOptions.contentType = request.contentType || 'application/json; charset=utf-8';
if (request.contentType) {
ajaxOptions.data = $.parseJSON(JSON.stringify(ajaxOptions.data));
} else {
ajaxOptions.data = JSON.stringify(ajaxOptions.data);
}
return $.ajax(ajaxOptions)
}
ajaxRequest(request);
}
I'm trying to call ajax request without using jquery. By using ECMA Script6:
var promise1 = new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
var url = urls.urlListChapters.replace(0, specificationId);
xhr.open('GET', url, true);
xhr.responseType = 'json';
xhr.onload = function() {
if (xhr.status === 200) {
alert(xhr.response);
resolve(xhr.response);
} else {
reject(new Error(xhr.statusText));
}
};
xhr.onerror = function() {
reject(new Error("Network error"));
};
xhr.send();
});
promise1.then(function(data) {
alert('Your public IP address is: ' + data);
}, function(status) {
alert('Something went wrong.');
});
I get as response "null". However, with my ol jquery method, I do get the list of objects.
$.ajax({
url: urls.urlListChapters.replace(0, specificationId),
dataType: 'json',
method: 'GET',
})
.done(function(data) {
var data = JSON.parse(data);
console.log(data);
alert(1)
})
.fail(function(jqXHR, textStatus, errorThrown){
console.log(jqXHR);
alert('WHAT!');
});
Is there something I'm missing?
I'm facing an issue with promises..and was banging my head around from almost an hour now...
this.getDocument(documentId)
.then(function (response) {
console.log('in first then')
return 'from first then';
}).then(function (response) {
console.log(response)
});
Ideally the above code should give following output
in first then
from first then
But the actual output is as follows
in first then
undefined
Now the problem here is why the second then is getting response as undefined when I'm returning something from the first then.
[EDIT 1] Adding getDoument code
function getDocument(documentID) {
var config = {
url: '<URL>' + documentID,
headers: {enter code here
'Content-Type': 'application/json'
}
};
return HttpRequest.get(config);
}
var HttpRequest = (function () {
function HttpRequest() {
}
HttpRequest.get = function (config) {
var deferred = Q.defer();
var http = new XMLHttpRequest();
var url = config.url;
var authToken = window.localStorage.getItem('token');
http.open("GET", url, true);
Object.keys(config.headers).map(function (k) {
http.setRequestHeader(k, config.headers[k]);
});
http.setRequestHeader("Authorization", 'Bearer ' + authToken);
http.onreadystatechange = function () {
if (http.readyState !== 4)
return;
var response = http.responseText;
if (http.status != 200)
return deferred.reject(response);
deferred.resolve(response);
// if (/^[^2]\d\d$/.exec(http.status)) return deferred.reject(http.status);
};
http.send();
return deferred.promise;
};
HttpRequest.post = function (config) {
};
return HttpRequest;
}());