In my components' ComponentDidMount life cycle method, I'm attempting to initiate an AJAX request to get data client-side (Data needs to be available when app has loaded). Upon inspection, I've noticed that my promise chain keeps deferring to the fail property. This is confusing because, upon inspection via the Chrome Developer tools, the request is made and data is successfully returned to the promise (see Screenshot). I suspected it could be the speed at how fast my component loads, and I tried a componentWillMount life cycle method, and it yields the same results. I was retrieving data fine, synchronously via an AJAX request, but I'm now trying to improve the code with asynchronously functionality.
new code tried:
componentDidMount: function(){
var returnedClassesString;
var user = window.globalValue;
function getQueries(user){
returnedClassesString = $.ajax("/portals/0/js/get_classes_front.aspx?userName="+user).done(function(data,err){
console.log('good' + data);
}).fail(function(data,err){
console.log(err);
});
}
getQueries(user);
},
componentDidMount method:
componentDidMount: function(){
var returnedClassesString;
var user = window.globalValue;
$.when($.ajax("/portals/0/js/get_classes_front.aspx?userName="+user)).then(function(data, textStatus, jqXHR) {
// Handle both XHR objects
console.log(data);
}).fail(function(){
console.log('failed');
});
}
Screenshot of Chrome Dev-Tools (Network Traffic, I request the first file in the stack):
Screenshot of Chrome Dev-Tools (JavaScript console w/ 'failed' message):
Issue was on my server-side code. Using .Net code-behind, switched Response.ContentType from Response.ContentType = "text/xml"; to Response.ContentType = "text";. Thank You to Dave Methvin for spotting out my JSON error. Code posted above in both examples still valid.
Related
I want to load some template files dynamically with the help of ajax. I have added the ajax $.get method for loading the html files and it's working fine with all browsers except safari browser.
In safari it gives me "Failed to load resource: cancelled" error when first time I open the url. However after I refresh my page again, it loads all the files.
When I open my url with http request instead of https, it can load the template file in first time on safari browser.
This issue only happens when I open the url with https. I have successfully installed the certificate and its working fine with other browser. Even there is no certificate issue in safari as well.
Here is my code
var decorator = {
init: function(book, cd) {
this.loadTPL(cd);
},
tpl: {
btnStart: "tpl/startBtn.html",
interfaceTpl: "tpl/interfaceTpl.html",
topMenu: "tpl/topMenu.html",
topMenuItem: "tpl/topMenuItem.html",
},
loadTPL: function(cbTpl) {
var self = this;
var objTpl = {};
async.forEachOf(this.tpl, function(value, key, callback) {
$.get(value, {}, function(data) {
//alert("Load was performed.");
//console.log(value, data);
objTpl[key] = data;
callback();
});
}, function(err, results) {
if (err) {
console.log(err);
}
self.tpl = objTpl;
cbTpl(err);
});
}
}
Any Idea?
While your approach "should" work, it goes into the weird unknown areas of JS, specially using the async lib. So, my solution basically involves refactoring all of it. Instead async you can use jQuery promises to fire all the gets you need, and then handle the responses/errors in each one of them with the promises handlers.
As an example:
$(templatesToLoad).each(function (element, index) {
$.ajax({element.url, cache: false })
.done(function (result) {
objTpl[key] = result;
element.allback(); // callback for each template
})
.fail(function () {
alert( "error" );
})
.always(function () {
alert( "completed" );
});
});
Note:$.get its just a sugar code for $.ajax. By default $.ajax performs a get, unless another method is specified.
The browser, whichever it is, will handle the calls and it will trigger each one of them as soon as permitted, based on each browser capabilities and limitations, so no need to worry about specific implementations.
As general rule, always remember to check the encoding of the calls and responses and their formats, json, text or whatever you use as a response format.
This is likely a cache/timeout issue. Try setting the ajax timeout to something huge. If that works, back it off until you find the sweet spot.
I'm introducing service worker on my site.And i'm using app-shell approach for responding to requests.Below is my code structure.
serviceWorker.js
self.addEventListener("fetch", function(event) {
if (requestUri.indexOf('-spid-') !== -1) {
reponsePdPage(event,requestUri);
}else{
event.respondWith(fetch(requestUri,{mode: 'no-cors'}).catch(function (error){
console.log("error in fetching => "+error);
return new Response("not found");
})
);
}
});
function reponsePdPage(event,requestUri){
var appShellResponse=appShellPro();
event.respondWith(appShellResponse); //responds with app-shell
event.waitUntil(
apiResponse(requestUri) //responds with dynamic content
);
}
function appShellPro(){
return fetch(app-shell.html);
}
function apiResponse(requestUri){
var message=['price':'12.45cr'];
self.clients.matchAll().then(function(clients){
clients.forEach(function (client) {
if(client.url == requestUri)
client.postMessage(JSON.stringify(message));
});
});
}
App-shell.html
<html>
<head>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.onmessage = function (evt) {
var message = JSON.parse(evt.data);
document.getElementById('price').innerHTML=message['price'];
}
}
</script>
</head>
<body>
<div id="price"></div>
</body>
</html>
serviceWorker.js is my only service worker file. whenever i'm getting request of -spid- in url i calls reponsePdPage function.In reponsePdPage function i'm first responding with app-shell.html. after that i'm calling apiResponse function which calls postmessage and send the dynamic data.The listener of post message is written in app-shell.html.
The issue i'm facing is, sometimes post message gets called before the listener registration.It means the apiResponse calls post message but their is not register listener to that event. So i cant capture the data.?Is their something wrong in my implementation.
I'm going to focus on just the last bit, about the communication between the service worker and the controlled page. That question is separate from many of the other details you provide, such as using PHP and adopting the App Shell model.
As you've observed, there's a race condition there, due to the fact that the code in the service worker and the parsing and execution of the HTML are performed in separate processes. I'm not surprised that the onmessage handler isn't established in the page yet at the time the service worker calls client.postMessage().
You've got a few options if you want to pass information from the service worker to controlled pages, while avoiding race conditions.
The first, and probably simplest, option is to change the direction of communication, and have the controlled page use postMessage() to send a request to the service worker, which then responds with the same information. If you take that approach, you'll be sure that the controlled page is ready for the service worker's response. There's a full example here, but here's a simplified version of the relevant bit, which uses a Promise-based wrapper to handle the asynchronous response received from the service worker:
Inside the controlled page:
function sendMessage(message) {
// Return a promise that will eventually resolve with the response.
return new Promise(function(resolve) {
var messageChannel = new MessageChannel();
messageChannel.port1.onmessage = function(event) {
resolve(event.data);
};
navigator.serviceWorker.controller.postMessage(message,
[messageChannel.port2]);
});
}
Inside the service worker:
self.addEventListener('message', function(event) {
// Check event.data to see what the message was.
// Put your response in responseMessage, then send it back:
event.ports[0].postMessage(responseMessage);
});
Other approaches include setting a value in IndexedDB inside the service worker, which is then read from the controlled page once it loads.
And finally, you could actually take the HTML you retrieve from the Cache Storage API, convert it into a string, modify that string to include the relevant information inline, and then respond with a new Response that includes the modified HTML. That's probably the most heavyweight and fragile approach, though.
I want to do an ajax call with vanilla js.
In jQuery, I have this working ajax call:
$.ajax({
url:"/faq/ajax",
datatype: 'json',
type:"POST",
data: {search:'banana'},
success:function(r) {
console.log(r['name'])
}
});
Vanilla JS:
var search = document.getElementById('searchbarfaq').value;
var r = new XMLHttpRequest();
r.open("POST", "/faq/ajax", true);
r.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) return;
console.log("Success: " + JSON.parse(r.responseText));
var a = JSON.parse(r.responseText);
console.log(a.name); //also tried a['name']...
};
r.send("search=banana");
The vanilla js call just logs this to the console:
"Success: [object Object]"
Array [ ]
Can someone tell me what I am doing wrong?
You haven't told the server how you are encoding the data in the request.
r.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
Presumably whatever server side handler you are using to process the data isn't parsing it correctly, so isn't finding the data it needs, and then returns a blank array as the result.
Beyond printing out r.responseText to the console, you can also inspect the HTTP response from dev tools built into the browser itself.
On Firefox, for instance:
Tools -> Web Developer -> Network
(this should open a panel listing all the HTTP requests and responses)
Go through the process you use to execute your AJAX call
Look at the corresponding HTTP request by clicking on the item in the list in the panel shown in step 1 (a panel on the right should appear with more details about the request and subsequent response)
Digging around in these tools can give you a lot of insight into the the HTTP request your code is making and the values it's getting back in the response.
A similar process can be performed for all the major browsers out there.
You can use this simple and lightweight Ajax module with the following syntax:
import {ajax} from '/path/to/ajax.min.js';
ajax('https://api_url.com')
.data('key-1','Value-1')
.data('key-2','Value-2')
.send()
.then((data) => { console.log ('success', data) })
.catch((status) => { console.log ('failed', status)} );
I have a nodejs application where I make some ajax request using jquery. In developer tools response of last ajax request is empty if I make redirection, otherwise response exists. Is there any logic to why wouldn't it show response in case of redirection.
I don't understand redirection is made in ajax callback and based on values from response, redirection is made properly which means response exist but chrome dev tools won't show it, What am i doing wrong?
here is my callback
.done(function (response)
{
if (response.errorCode == "00") {
//window.location = "/"; //no response shown if dev tools if i uncomment this
console.log("Yeah i got some response " + response);
}
})
Make sure Preserve the log upon navigation is enabled in chrome dev tools settings.
Let
window.location = '/whatever/address';
be the last thing you call, or do it later using
setTimeout( function () {
window.location = '/whatever/address';
}, 1);`
Beware that all values of variables will be lost on a new page load / navigation
After redirection everything gets reloaded that's why you are not able to access response.
To solve this you can first use your response object & then redirect your page.
I'm trying to implement comet in my application and, being inexperienced with JavaScript, I'm not sure how to do the client side.
When the server receives a request, it just keeps it open and writes data to it when necessary:
def render_GET(self, request):
print "connected"
request.write("Initiated\r\n")
reactor.callLater(random.randint(2, 10), self._delay, request)
return NOT_DONE_YET;
def _delay(self, request):
print "output"
self.count += 1
request.write("Hello... {0}\r\n".format(self.count))
reactor.callLater(random.randint(2, 10), self._delay, request)
I've been using jQuery on the client side so far, but I can't figure out how to make it work with the server. I've been looking at the jQuery.AJAX documentation and none of the callbacks say "Hey! I just received some data!", they only say "The request is finished."
I thought the dataFilter() function was what I wanted since it lets you handle the raw data before the request finishes, but it only lets you do it just before the request finishes, and not as you receive data.
So how can I receive data continuously through an open request? As you can see in the python example, each piece of data is delimited with \r\n so I want the JavaScript to behave like a line receiver. Is this possible with jQuery or do I have to play with XMLHttpRequest/ActiveXObject directly? Is there a (simple, lightweight) library available which implements a line receiver for me?
I'm hoping to hear about an existing library and how to implement this myself, since I've had bad bad luck with comet libraries so far, and at this point I'm hoping to just write the code I need and not bother with an entire library.
After looking at some other Comet/jQuery questions, I stumbled across this: http://code.google.com/p/jquerycomet/, which looks to be a jQuery plugin that does what you're after. If you're looking to see how it works, I'd just dig into the source.
The question where I found some great information is here.
A standard technique is to do a long polling request via AJAX (standard call with a really long timeout), then when receiving a response have your callback initiate another long poll when it is invoked. If the timeout expires, then you reissue the request using the error handling mechanism. Rather than having a single long request that periodically does something (like the "infinite iframe" technique), this uses a series of long requests to get data as the server has it available.
function longPoll( url, data, cb )
{
$.ajax({
url: url,
data: data,
timeout: Number.MAX_VALUE,
...other options...
success: function(result) {
// maybe update the data?
longPoll( url, data, cb );
cb.call(this,result);
},
error: function() {
longPoll( url, data, cb );
}
}
}
this code is the simpliest I have ever seen.
var previous_response_length = 0
, xhr = new XMLHttpRequest();
xhr.open("GET", "http://127.0.0.1:7379/SUBSCRIBE/hello", true);
xhr.onreadystatechange = checkData;
xhr.send(null);
function checkData() {
if(xhr.readyState == 3) {
response = xhr.responseText;
chunk = response.slice(previous_response_length);
previous_response_length = response.length;
console.log(chunk);
}
};