HttpMethod.CallHttpPOSTMethod('POST',null, path).success(function (response) {
console.log(response);
$scope.htmlString = $sce.trustAsHtml(response.data[0]);
$timeout(function () {
var temp = document.getElementById('form');
if (temp != null) {
temp.submit();
}
}, 0);
});
I will get html string in RESPONSE of my API call. And then I will add the html to my view page.
If I write the code outside $timeout service it wont work as it will work when written inside $timeout service.
What is the difference between two ways?
How is $timeout useful here?
When you make any changes to the controller, it does not start asynchronously for two-way binding. If the asynchronous code is wrapped in special ones: `$timeout, $scope.$apply, etc. binding will happen. For the current code example, I would have tried replace you code to:
HttpMethod.CallHttpPOSTMethod('POST',null, path).success(function (response) {
console.log(response);
$scope.htmlString = $sce.trustAsHtml(response.data[0]);
var temp = document.getElementById('form');
if (temp != null) {
temp.submit();
}
$scope.$apply();
});
I tried to give you an answer in very simple language, hope it may help to understand your issue.
Generally, When HTTP request fires to execute it will send to the server and get the data from the server this is the general scenario we have in our mind. There may be a situation occur that sometime due to network latency it may possible to receive response delay.
AngluarJs application has its own lifecycle.
Root scope is created during application bootstrap by the $injector. In template linking, directive binding creates new child scope.
While template linking there is watch registered to particular scope to identify particular changes.
In your case, when template linking and binding directive, there is a new watcher registered. Due to network latency or other reason your $http request sends delay response to your $http request and meanwhile those time scope variable has been changed. due to that, it will not give the updated response.
When you send $http request to a server it is asynchronous operation. When you use $timeout ultimately your scope binding wait to numbers of seconds in $timeout function you defined. After n number of seconds, your scope variable watch has been executed and it will update the value if you get the response in time.
Related
I am trying to write a Google Apps script which has a client and server side component. The client side component displays a progress bar. The client calls server side functions (which are called asynchronously), whose progress has to be shown in the client side progress-bar. Now, what I want is to be able to update the client side progress bar based on feedback from the server side functions. Is this possible?
The complexity is created due the the fact that JS makes the server-side calls asynchronously and hence I cannot really have a loop on the client side calling the functions and updating the progress bar.
I could of course split up the execution of the server side function in multiple steps, call one by one from the client side, each time updating the status bar. But I'm wondering if there's a better solution. Is there a way to call a client side function from the server side, and have that update the progress bar based on the argument passed? Or is there a way to access the client side progress-bar object from server side and modify it?
The way I've handled this is to have a middleman (giving a shout out now to Romain Vialard for the idea) handle the progress: Firebase
The HTML/client side can connect to your Firebase account (they're free!) and "watch" for changes.
The client side code can update the database as it progresses through the code - those changes are immediately fed back to the HTML page via Firebase. With that, you can update a progress bar.
Romain has a small example/description here
The code I use:
//Connect to firebase
var fb = new Firebase("https://YOUR_DATABASE.firebaseio.com/");
//Grab the 'child' holding the progress info
var ref = fb.child('Progress');
//When the value changes
ref.on("value", function(data) {
if (data.val()) {
var perc = data.val() * 100;
document.getElementById("load").innerHTML = "<div class='determinate' style='width:" + perc + "%\'></div>";
}
});
On the client side, I use the Firebase library to update the progress:
var fb = FirebaseApp.getDatabaseByUrl("https://YOUR_DATABASE..firebaseio.com/");
var data = { "Progress": .25};
fb.updateData("/",data);
Rather than tying the work requests and progress updating together, I recommend you separate those two concerns.
On the server side, functions that are performing work at the request of the client should update a status store; this could be a ScriptProperty, for example. The work functions don't need to respond to the client until they have completed their work. The server should also have a function that can be called by the client to simply report the current progress.
When the client first calls the server to request work, it should also call the progress reporter. (Presumably, the first call will get a result of 0%.) The onSuccess handler for the status call can update whatever visual you're using to express progress, then call the server's progress reporter again, with itself as the success handler. This should be done with a delay, of course.
When progress reaches 100%, or the work is completed, the client's progress checker can be shut down.
Building on Jens' approach, you can use the CacheService as your data proxy, instead of an external service. The way that I've approached this is to have my "server" application generate an interim cache key which it returns to the "client" application's success callback. The client application then polls this cache key at an interval to see if a result has been returned into the cache by the server application.
The server application returns an interim cache key and contains some helper functions to simplify checking this on the client-side:
function someAsynchronousOperation() {
var interimCacheKey = createInterimCacheKey();
doSomethingComplicated(function(result) {
setCacheKey(interimCacheKey, result);
});
return interimCacheKey;
}
function createInterimCacheKey() {
return Utilities.getUuid();
}
function getCacheKey(cacheKey, returnEmpty) {
var cache = CacheService.getUserCache();
var result = cache.get(cacheKey);
if(result !== null || returnEmpty) {
return result;
}
}
function setCacheKey(cacheKey, value) {
var cache = CacheService.getUserCache();
return cache.put(cacheKey, value);
}
Note that by default getCacheKey doesn't return. This is so that google.script.run's successHandler doesn't get invoked until the cache entry returns non-null.
In the client application (in which I'm using Angular), you call off to the asynchronous operation in the server, and wait for its result:
google.script.run.withSuccessHandler(function(interimCacheKey) {
var interimCacheCheck = $interval(function() {
google.script.run.withSuccessHandler(function(result) {
$interval.cancel(interimCacheCheck);
handleSomeAsynchronousOperation(result);
}).getCacheKey(interimCacheKey, false);
}, 1000, 600); // Check result once per second for 10 minutes
}).someAsynchronousOperation();
Using this approach you could also report progress, and only cancel your check after the progress reaches 100%. You'd want to eliminate the interval expiry in that case.
In angular 2+, I have a component A which calls service A where i make some changes and call service B (Http Calls) and get the data which is simply passed back to service A, now i need to subscribe into service A to see the data and also subscribe into Component A to display data there?
why i need to subscribe at 2 places which means its making the http calls twice (which is not good at all)
what is the best way where I can fetch and store data in Service A by subscribing and do all manipulation and simply send that object back to component A to display it? even I try to make a variable in subscribing section in service A but when I try to log that variable outside the subscribe block. it is undefined.
thanks for the help.
while searching for the answer, I found one way (or can called worked around) that is to use "async-await" feature in angular with HttpClient.
which will basically wait at the same line of execution till you get result (success or error). and then proceed further with next line of execution.
for example:
async myFunction() {
this.myResult = await this.httpClient.get(this.url).toPromise();
console.log('No issues, it will wait till myResult is populated.');
}
Explanation:
adding async in front of the function to let it know that execution need to wait and the desire place (mostly at http service call as I need to wait till I get the result) we put await. so execution will go under wait period till it get the response back. and later. simply return the variable.
We have images that redirect from our media server to a CDN that I'm trying to exclude from my service worker logic to work around the bug in Chrome 40. In Canary the same worker is able to work just fine. I thought there was an event.default() to fall back to the standard behavior but I don't see that in Chrome's implementation, and reading the spec it seems like the current recommendation is to just use fetch(event.request).
So the problem I have is do I have to wait until 99% of all of our users move to Chrome 41+ in order to use service workers in this scenario, or is there some sort of way I can opt out for certain requests?
The core of my logic is below:
worker.addEventListener('install', function(event){
event.waitUntil(getDefaultCache().then(function(cache){
return cache.addAll(precacheUrls);
}));
});
worker.addEventListener('fetch', function(event){
event.respondWith(getDefaultCache().then(function(cache){
return cache.match(event.request).then(function(response){
if (!response){
return fetch(event.request.clone()).then(function(response){
if (cacheablePatterns.some(function(pattern){
return pattern.test(event.request.url);
})) {
cache.put(event.request, response.clone());
}
return response;
});
}
return response;
});
}));
});
Once you're inside a event.respondWith() you do need to issue a response or you'll incur a Network Error. You're correct that event.default() isn't currently implemented.
A general solution is to not enter the event.respondWith() if you can determine synchronously that you don't want to handle the event. A basic example is something like:
function fetchHandler(event) {
if (event.request.url.indexOf('abc') >= 0) {
event.respondWith(abcResponseLogic);
} else if (event.request.url.indexOf('def') >= 0) {
event.respondWith(defResponseLogic);
}
}
self.addEventListener('fetch', fetchHandler);
If event.respondWith() isn't called, then this fetch handler is a no-op, and any additional registered fetch handlers get a shot at the request. Multiple fetch handlers are called in the order in which they're added via addEventListener, one at a time, until the first one calls event.respondWith().
If no fetch handlers call event.respondWith(), then the user agent makes the request exactly as it normally would if there were no service worker involvement.
The one tricky thing to take into account is that the determination as to whether to call event.respondWith() needs to be done synchronously inside each fetch handler. Anything that relies on asynchronous promise resolution can't be used to determine whether or not to call event.respondWith(). If you attempt to do something asynchronous and then call event.respondWith(), you'll end up with a race condition, and likely will see errors in the service worker console about how you can't respond to an event that was already handled.
I've read many posts about this but still can't wrap my head around fixing my problem. I've looked at jQuery.when but not sure how to use it. I get data from the server via ajax and then it updates the page. Sometimes, it might take a few seconds depending on how much data is being returned. I don't want that same ajax function to run until all html has loaded on the page. Is that possible?
I have a timer to run a function that calls an ajax request.
setInterval( "update()", 25000 );
This is the ajax inside the update function
$.ajax({
type: "POST",
url: "/ajax/modify.php",
data: "id="+ id +"& action="+ act,
success: function(response){
//update the html on the page
}
});
There is a way for the user to get more posts by clicking on a link. Well problem is, if they click that link to get more posts and the timer happens right after, it refreshes the page and interrupts the users request and reloads the div container with what was there before. So I need it to wait until the response has completed and the page has been updated before allowing more requests.
An example what be appreciated.
JQuery's ajax method returns a promise, which you can use to attach callbacks. You can store away this promise into a variable. On success/fail of the function, you can clear the variable. This way you know if a request is currently active or not. Just make sure the variable is outside the function scope or it won't do anything to help you. For example:
var currentRequest = null;
function doUpdate() {
// don't do anything if there's an active request
if (currentRequest)
return;
currentRequest = $.ajax({
type: "POST",
url: "/ajax/modify.php",
data: "id="+ id +"& action="+ act
}).then(function(response) {
// do your UI updates here.
}).always(function() {
// whether the call succeeds or not, still clear out the request
// so that the next call into the function makes a new request
currentRequest = null;
});
}
have a look at this SO question jQuery deferreds and promises - .then() vs .done()
jQuery Deffered Object
doing async:false kills the purpose of it, you can fire the next ajax request in the success call back of the first one but that is not a clean approach IMO
We can use the web worker in HTML5 like this:
var worker = new Worker('worker.js');
but why can't we call a function like this?
var worker = new Worker(function(){
//do something
});
This is the way web workers are designed. They must have their own external JS file and their own environment initialized by that file. They cannot share an environment with your regular global JS space for multi-threading conflict reasons.
One reason that web workers are not allowed direct access to your global variables is that it would require thread synchronization between the two environments which is not something that is available (and it would seriously complicate things). When web workers have their own separate global variables, they cannot mess with the main JS thread except through the messaging queue which is properly synchronized with the main JS thread.
Perhaps someday, more advanced JS programmers will be able to use traditional thread synchronization techniques to share access to common variables, but for now all communication between the two threads must go through the message queue and the web worker cannot have access to the main Javascript thread's environment.
This question has been asked before, but for some reason, the OP decided to delete it.
I repost my answer, in case one needs a method to create a Web worker from a function.
In this post, three ways were shown to create a Web worker from an arbitrary string. In this answer, I'm using the third method, since it's supported in all environments.
A helper file is needed:
// Worker-helper.js
self.onmessage = function(e) {
self.onmessage = null; // Clean-up
eval(e.data);
};
In your actual Worker, this helper file is used as follows:
// Create a Web Worker from a function, which fully runs in the scope of a new
// Worker
function spawnWorker(func) {
// Stringify the code. Example: (function(){/*logic*/}).call(self);
var code = '(' + func + ').call(self);';
var worker = new Worker('Worker-helper.js');
// Initialise worker
worker.postMessage(code);
return worker;
}
var worker = spawnWorker(function() {
// This function runs in the context of a separate Worker
self.onmessage = function(e) {
// Example: Throw any messages back
self.postMessage(e.data);
};
// etc..
});
worker.onmessage = function() {
// logic ...
};
worker.postMessage('Example');
Note that the scopes are strictly separated. Variables can only be passed and forth using worker.postMessage and worker.onmessage. All messages are structured clones.
This answer might be a bit late, but I wrote a library to simplify the usage of web workers and it might suit OP's need. Check it out: https://github.com/derekchiang/simple-worker
It allows you to do something like:
SimpleWorker.run({
func: intensiveFunction,
args: [123456],
success: function(res) {
// do whatever you want
},
error: function(err) {
// do whatever you want
}
})
WebWorkers Essentials
WebWorkers are executed in an independent thread, so have no access to the main thread, where you declare them (and viceversa). The resulting scope is isolated, and restricted. That's why, you can't , for example, reach the DOM from inside the worker.
Communication with WebWorkers
Because communication betwen threads is neccessary, there are mechanisms to accomplish it. The standard communication mechanism is through messages, using the worker.postMessage() function and the worker.onMessage(), event handler.
More advanced techniques are available, involving sharedArrayBuffers, but is not my objective to cover them. If you are interested in them, read here.
Threaded Functions
That's what the standard brings us.
However, ES6 provides us enough tools, to implement an on-demmand callable Threaded-Function.
Since you can build a Worker from a Blob, and your Function can be converted into it (using URL.createObjectURL), you only need to implement some kind of Communication Layer in both threads, to handle the messages for you, and obtain a natural interaction.
Promises of course, are your friend, considering that everything will happen asynchronously.
Applying this theory, you can implement easilly, the scenario you describe.
My personal approach : ParallelFunction
I've recently implemented and publised a tiny library wich does exactly what you describe. in less than 2KB (minified).
It's called ParallelFunction, and it's available in github, npm , and a couple of CDNs.
As you can see, it totally matches your request:
// Your function...
let calculatePi = new ParallelFunction( function(n){
// n determines the precision , and in consequence
// the computing time to complete
var v = 0;
for(let i=1; i<=n; i+=4) v += ( 1/i ) - ( 1/(i+2) );
return 4*v;
});
// Your async call...
calculatePi(1000000).then( r=> console.log(r) );
// if you are inside an async function you can use await...
( async function(){
let result = await calculatePi(1000000);
console.log( result );
})()
// once you are done with it...
calculatePi.destroy();
After initialization, you can call your function as many times you need. a Promise will be returned, wich will resolve, when your function finishes execution.
By the way, many other Libraries exists.
Just use my tiny plugin https://github.com/zevero/worker-create
and do
var worker_url = Worker.create(function(e){
self.postMessage('Example post from Worker'); //your code here
});
var worker = new Worker(worker_url);
While it's not optimal and it's been mentioned in the comments, an external file is not needed if your browser supports blobURLs for Web Workers. HTML5Rocks was the inspiration for my code:
function sample(e)
{
postMessage(sample_dependency());
}
function sample_dependency()
{
return "BlobURLs rock!";
}
var blob = new Blob(["onmessage = " + sample + "\n" + sample_dependency]);
var blobURL = window.URL.createObjectURL(blob);
var worker = new Worker(blobURL);
worker.onmessage = function(e)
{
console.log(e.data);
};
worker.postMessage("");
Caveats:
The blob workers will not successfully use relative URLs. HTML5Rocks link covers this but it was not part of the original question.
People have reported problems using Blob URLs with Web Workers. I've tried it with IE11 (whatever shipped with FCU), MS Edge 41.16299 (Fall Creator's Update), Firefox 57, and Chrome 62. No clue as to Safari support. The ones I've tested have worked.
Note that "sample" and "sample_dependency" references in the Blob constructor call implicitly call Function.prototype.toString() as sample.toString() and sample_dependency.toString(), which is very different than calling toString(sample) and toString(sample_dependency).
Posted this because it's the first stackoverflow that came up when searching for how to use Web Workers without requesting an additional file.
Took a look at Zevero's answer and the code in his repo appears similar. If you prefer a clean wrapper, this is approximately what his code does.
Lastly -- I'm a noob here so any/all corrections are appreciated.
By design web workers are multi-threaded, javascript is single threaded"*"multiple scripts cannot run at the same time.
refer to: http://www.html5rocks.com/en/tutorials/workers/basics/