While loop not executing inside callback - javascript

Inside the catch of a promise
.catch((message) => {
console.log(message)
var newUrl = url
chrome.tabs.create({url: newUrl}, function(response) {
console.log(response.status)
status = 'loading'
while (status == 'loading') {
setTimeout(function() {
console.log(response.status)
status = response.status
}, 3000)
}
})
})
I'm trying to write the catch in the way that it will open up a new page, wait for it to finish loading, then grab the new cookies
I feel like Im taking crazy pills as this seems super straight forward. However its never printing out response.status
I want it to wait to check response.status every 3 seconds and once the page has loaded it will end the loop.
What am I doing wrong?

The way You've wrote it you've made an infinite loop, which will put tons of setTimeouts on browser's event queue.
setTimeout also put's code there, but it puts it with "3sec plus" delay note.
In practice you tell your browser - set infinite timeouts for me, and after it's finished, please do console.log after 3 seconds. This won't happen.
You should probably use setInterval instead

Related

How do I tell puppeteer when the page is fully loaded?

I have some things which load asyncronously, so I need puppeteer to wait until they are finished loading.
I've tried waiting for a variable to be set
await page.waitForFunction('window.exampleLoaded === true');
I've tried waiting for an element to appear
await page.waitForSelector('#complete');
And I put this code directly in the javascript for the page:
window.exampleLoaded = true;
document.body.insertAdjacentHTML('beforeend','<div id="complete"></div>');
But puppeteer just times out, those waitFor's never resolve.
If i just open the page in the browser, both window.exampleLoaded === true and document.querySelector('#complete')!=null are true.
EDIT: If I put them at the very top of the code, then the awaits resolve. But not if they're triggered later.
What am I doing wrong?
The problem was something else on the page, but this code was very helpful in figuring out the problem:
page
.on('console', message =>
console.log(`${message.type().substr(0, 3).toUpperCase()} ${message.text()}`))
.on('pageerror', ({ message }) => console.log(message))
.on('response', response =>
console.log(`${response.status()} ${response.url()}`))
.on('requestfailed', request =>
console.log(`${request.failure().errorText} ${request.url()}`))

How to waitFor when page refreshes in Puppeteer?

I have an app I'm working with that is behaving like this... You visit a url /refresh, and it loads the page with a loader/spinner/bar showing for like 5 seconds, then it refreshes the page after it's done. It does this so it can load the latest data that was computed during /refresh.
Right now I am just setting a timeout longer than the loader will most likely stay around, but this is brittle because a bad network connection could put it over the line.
How can I instead "watch" for when the refresh happens? What technique would you recommend. It seems to start to get hairy pretty fast.
Into the nitty gritty, when the loader is showing, when it finishes it is gone for like a half a second before the page reload. So I can't just wait til the loader is gone. It seems like I need to keep some sort of state variable around in the DOM like in localStorage, but can't pinpoint it. Would love some help.
well you could "watch" for the element that display the data using page.$(selector), or if no such element you could also wait for the specific request 's response:
const waitForResponse = (page, url) => {
return new Promise(resolve => {
page.on("response", function callback(response){
if (response.url() === url) {
resolve(response);
page.removeListener("response",callback)
}
})
})
};
const res = await waitForResponse(page,"url of the request you want to wait for");
Wait for Network request before continuing process

How to suppress FuncUnit unit errors in tests?

I have a FuncUnit test case wherein I open a webpage using
F.open("http://www.example.com");
There is a known issue in our page that approximately one in around 20 times the webpage would not load for whatever reason. I want to retry when it does not load. But in FuncUnit there is no way to suppress error if it fails to load the page. Is there a way to suppress error message in Funcunit?
Couldn't something like this work for you?
module("test", {
setup: function() {
let startMeUp = () => F.open('http://www.example.com'); // unfortunately doesn't return a usable value
let checkCondition = () => {
// grab F(F.window), and check for a known element in the page
return elementFound;
};
while(!checkCondition()) {
// element wasn't found, so let's try it again
startMeUp();
// maybe set a wait here
}
}
});
var url = "http://www.example.com"
F.get(url, function(data){
console.log("Made an ajax call to make sure that F.open is always second call");
})
// Wait for few seconds before making the actual F.open
F.wait(5000,function(){
F.open(url);
})
Whenever F.open fails ( i.e during one out of 20 times) I noticed that the second test point that uses F.open passes.However I cannot do F.open again in case the first one does not work as there is no way to suppress F.open error when the page does not load.
So I always make a simple ajax call before making the actual F.open. This is not the right way to do it but it works for us as we don't actually care whether the page is a first/second time load in our tests.

Issue trying to run synchronous REST requests in Node

First of all, I'm not experienced in asynchronous programming, so I'm sorry if I missed something obvious.
I see this question pop up a lot. I know that people don't like forcing synchronicity in Javascript, but it is necessary in this case. I'm making heavy calls to a production database that can't take too much load due to how frequently it is used. Because of this, I'm setting up my code in a loop to make a request, wait for confirmation that it is finished, sleep for 2 seconds, and then make the next request. This is because I'm going to be pulling a LOT of data from this server on a weekly basis over the course of around 10-20 minutes.
Here's the code that I have. Sleep is a function that forces the program to wait using the Date class.
var thread = function(cb){
cb();
};
do{
var x = thread(function(){
request.post(options, function(e, r, body){
console.log(e);
console.log(r.statusCode);
issues.push(body["issues"]);
maxResults = body["total"];
options.body.startAt += 25;
console.log("Going to sleep");
});
sleep(2000);
});
console.log("Waking up and moving to the next cycle");
}while(issues.length < maxResults);
console.log("Finished with the requests");
}
although I have a callback set up, my code is still running the requests asynchronously. Because I leave maxResults null, it is plainly obvious that my callback isn't working. This is my output:
Waking up and moving to the next cycle
Finished with the requests
Going to sleep
You need to make a recursive asynchronous function.
It would look something like this:
function fetch(existingIssues) {
return sendRequest().then(function() {
existingIssues.push(...);
if (existingIssues.length >= maxResults)
return existingIssues;
else
return fetch(existingIssues);
});
}
fetch([]).then(...);

Check Pending AJAX requests or HTTP GET/POST request

How do i check if the page has pending AJAX or HTTP GET/POST requests? I use javascript and/or python for this checking.
what i wanted to do is execute a script if a page has finished all requests. onload doesn't work for me, if you used firebugs net panel, you would know. onload fires when the page is loaded but there is a possibility that there are still pending request hanging around somewhere.
thank you in advance.
figured it out. thanks for the effort guys.
just plain and simple javascript.
interValRef = 0;
interValRef = setInterval("checkState();",100)
function checkState(){
if(document.readyState == 'complete'){
clearInterval(interValRef);
myFunc();
}
}
Here is the best way of checking it.
var loadingDone = document.readyState=="complete" && jQuery.active === 0;
So loadingDone will be true, if Ajax calls are done. If its false then you can add waiting.
I see you mention you are using Prototype.js. You can track active requests with Prototype by checking the Ajax.activeRequestCount value. You could check this using setTimeout or setInterval to make sure that any requests triggered on page load have completed (if that's what you're looking to do)
Assuming you are using prototype.js you could keep track with a counter of all your request objects
var ACTIVE_REQUESTS = 0; // GLOBAL
ACTIVE_REQUESTS++
new Ajax.Request('/your/url', {
onSuccess: function(response) {
ACTIVE_REQUESTS--;
// Handle the response content...
}
}));
console.log("there are " + ACTIVE_REQUESTS + " open AJAX requests pending");
You would need to keep track of each XMLHttpRequest and monitor whether it completes or the asynchronous callback is executed.
I think you want to know if the HTML is fully loaded. In this case you can use the dom:loaded event. Here is an example on how to use it with prototype (but there must be a variant for other JS frameworks):
document.observe("dom:loaded", function() {
// do whatever you want to do
});
This event will fire as soon as the DOM tree is loaded. So even before all the images or external data (including iframe) are loaded.
I can confirm that document.readyState can still be 'complete' even if there are pending requests in network tab.
The code I developed for now to check if the page has been loaded completely or not is:
var prevSize= document.body.innerHTML.length;
var id= setInterval(()=>{
let currSize=document.body.innerHTML.length;
if(prevSize===currSize){
clearInterval(id);
console.log("page loaded successfully");
}
else{
console.log("loading...");
prevSize=currSize;
}
}, 3000)
This checks document.body.innerHTML length in every 3s.
Not a best solution, but atleast it works.
document.addEventListener("readystatechange", function(event) {
if (document.readyState === "complete") {
console.log("complete");
}
});

Categories

Resources