How can I prevent reloading of javascript in camel? - javascript

I am a starter for camel.
I used javascript for validation logic implement in camel xml.
Initially, it takes some time to load javascript when the first event(a file with some records) comes in. This situation is find.
In this case, only the first record is slow because of loading time of javascript and the rest of the records is normally performed.
The problem is that next event(a file) is coming in.
Camel tries to load javascript again. So, it takes loading time to process each file, so the overall performance has been degraded.
I want to modify some logic so that camel can only load it once.
How can I solve this problem?
<unmarshal id="_FileParsing">
<bindy
classType="com.openmzn.ktds.dao.volte.input.VoLTEBody"
locale="korea" type="Fixed"/>
</unmarshal>
<to id="_validateParsing" uri="language:javascript:classpath:spring/rules/volte/volte.js"/>
<multicast id="_FileDistributor" parallelProcessing="false">
<toD id="_ProcessNRat" uri="direct:NRAT"/>
<toD id="_ProcessDrop" uri="direct:DROP"/>
</multicast>
Javascript File
var bodyList = exchange.in.getBody(ArrayList.class);
if(!CollectionUtils.isEmpty(bodyList)) {
for (total_count = 0; total_count < bodyList.size(); total_count++) {
uBody = bodyList[total_count];
enriched = enrich(uBody);
result = validate(enriched);
resultList.add(result);
...
}
function enrich(uBody) {
...
}
function validate(enriched) {
...
}

You can turn on cacheScript=true, see the docs
https://github.com/apache/camel/blob/master/docs/components/modules/ROOT/pages/language-component.adoc

Related

How to make the client-side code wait for the full execution of google.script.run?

I've got a Google Apps Script WebApp that relies on an array of objects that are generated from a Google Spreadsheet. The app uses jquery and miniSearch to provide user functionality.
Currently, I run the server-side function with a success handler at the beginning of the HTML tag and update a "global" variable with the array of objects declared before it.
Index.html:
<script>
let data
google.scripts.run
.withSuccessHandler(payload=>{
data = payload}).getLinks() //[{link:body}, {link1:body1}]
setTimeout(()=>{
const documents = data
miniSearch = new miniSearch(...)
miniSearch.addAll(documents)}, 2500)
...
</script>
Code.gs
function getLinks(){
.
.
.
let values = sheet.getRange(1, 1, lastRow, lastCol)
for (let row = 0; row < lastRow; row++) {
let entry = new Data(row + 1, values[row][0], values[row][1], values[row][2], values[row][3], values[row][4], values[row][5], values[row][6])
allTitles.push(entry)
}
return allTitles
}
I simulate waiting for the google.scripts.run to finish by setting a setTimeout of 2500ms on the miniSearch indexing execution (which relies on the aforementioned array) and most of the time it works.
The problem is, that before the app is ran for the first time in a given period, the contents are not cached and the execution takes longer than the setTimeout, thus, as expected, the searching function bugs out since it's got no data to run on.
My question is: How to make the code wait and confirm that google.scripts.run has returned the needed data?
I have tried doing it with regular promises or async await functions, but to my understanding, google runs its server functions asynchronously and there's no way to tell (in code, that is) if it's finished, I've tried running it as $(function(){google.script.run..}) as to try to load the contents as soon as the DOM is loaded, but to no avail..
The only way to make sure it finishes is to do this. If its unresponsive then the problem lies in getLinks, Data, or whatever miniSearch is.
<script>
const documents = null;
google.scripts.run.withSuccessHandler( function(payload) {
documents = payload;
miniSearch = new miniSearch(...);
miniSearch.addAll(documents);
}.getLinks(); //[{link:body}, {link1:body1}]
...
</script>

How to manually insert js code on each load of page via the console of the browser

I am preparing JavaScript code that shows a random number for user as follows: if the user spend more than two minutes to pass to the next web page or if the actual page has the GET parameter "&source", the random number is replaced by another one. otherwise, the same random number is displayed for all the web pages.
The problem is that the JavaScript code should be executed manually from browser console on each page load: I should prepare a code that can be integrated to any web page from console.
Is there any difference from the normal case (include script with<script></script>)
Thanks for posting! In future posts, please try to provide some code or an example of something you've tried previously.
Anyways, here is a brief example of a script that will check for an existing number, check to see if there is a &source parameter set, begin the timer if there isn't one, and generate a new number if the timer finishes or the parameter is set.
To save the information between pages, you should consider using window.localStorage. This will allow you to check for and save the number to be used on later loads.
Note that this snippet isn't going to work until you bring it into your own page. Also, as #Sorin-Vladu mentioned, you'll have to use a browser extension if you don't have access to modify the pages you're running the script on.
const timeout = 120000
// This can be replaced by your manual execution
window.onload = () => {
start()
}
function start() {
// Attempt to pull the code from storage
let code = localStorage.getItem('code')
console.log(code)
// Get the URL parameters
let urlParams = new URLSearchParams(window.location.search)
// Check to see if the source parameter exists
if (!urlParams.has('source')) {
// If not, begin the timer
setTimeout(() => {
setCode()
}, timeout)
} else {
setCode()
}
}
function setCode() {
const code = Math.floor(Math.random() * 1000000)
localStorage.setItem('code', code)
console.log(code)
}

Updating content in a Google Apps Script sidebar without reloading the sidebar

I am using the following Google Apps Script code to display content in a custom sidebar of my spreadsheet while the script runs:
function test() {
var sidebarContent = '1<br>';
updateSidebar(sidebarContent);
sidebarContent += '2<br>';
updateSidebar(sidebarContent);
sidebarContent += '3';
updateSidebar(sidebarContent);
}
function updateSidebar(content) {
var html = HtmlService.createHtmlOutput(content)
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setTitle('Sidebar')
.setWidth(250);
SpreadsheetApp.getUi().showSidebar(html);
}
It works, but each time the updateSidebar() function runs, the sidebar blinks when loading in the new content.
How can I program this to update the content of the sidebar more efficiently, thus removing the blink?
I'm assuming that SpreadsheetApp.getUi().showSidebar(html); should really only be run once, at the beginning, and the subsequent updates to the content should be handled by Javascript in a .js file.
But I don't know how to get the sidebarContent variable from Javascript code running client-side in the user's browser.
Also, I know this must be possible, because I just saw this post on the Google Apps Developer Blog today about an app that uses a custom sidebar, and the .gif towards the end of the article shows a nicely-animated sidebar that's being updated in real-time.
I believe the solution for this situation is to actually handle the flow of the server-side script from the client-side. That is the only way I can think of right now to pass data to the client side from the server without re-generating the HTML.
What I mean by this is that you would want to make the calls to the server-side functions from the client, and have them return a response as a success handler to the client. This means that each action that needs to be logged will need to be made into its own function.
Ill show you a quick example of what I mean.
Lets say your server-side GAS code looked like this:
function actionOne(){
...insert code here...
return true;
}
function actionTwo(){
...insert code here...
return true;
}
And so on for as many actions need to be executed.
Now, for your .html file, at the bottom you would have javascript looking something like this:
<script>
callActionOne();
function callActionOne(){
google.script.run.withSuccessHandler(callActionTwo).actionOne();
}
function callActionTwo(){
...update html as necessary to indicate that the first action has completed...
google.script.run.withSuccessHandler(actionsComplete).actionTwo();
}
function actionsComplete(){
..update html to indicate script is complete...
}
</script>
It is a bit more complex than is ideal, and you might need to use the CacheService to store some data in between actions, but it should help you with your problem.
Let me know if you have any questions or if this doesn't fit your needs.

How to structure my code to return a callback?

So I've been stuck on this for quite a while. I asked a similar question here: How exactly does done() work and how can I loop executions inside done()?
but I guess my problem has changed a bit.
So the thing is, I'm loading a lot of streams and it's taking a while to process them all. So to make up for that, I want to at least load the streams that have already been processed onto my webpage, and continue processing stream of tweets at the same time.
loadTweets: function(username) {
$.ajax({
url: '/api/1.0/tweetsForUsername.php?username=' + username
}).done(function (data) {
var json = jQuery.parseJSON(data);
var jsonTweets = json['tweets'];
$.Mustache.load('/mustaches.php', function() {
for (var i = 0; i < jsonTweets.length; i++) {
var tweet = jsonTweets[i];
var optional_id = '_user_tweets';
$('#all-user-tweets').mustache('tweets_tweet', { tweet: tweet, optional_id: optional_id });
configureTweetSentiment(tweet);
configureTweetView(tweet);
}
});
});
}};
}
This is pretty much the structure to my code right now. I guess the problem is the for loop, because nothing will display until the for loop is done. So I have two questions.
How can I get the stream of tweets to display on my website as they're processed?
How can I make sure the Mustache.load() is only executed once while doing this?
The problem is that the UI manipulation and JS operations all run in the same thread. So to solve this problem you should just use a setTimeout function so that the JS operations are queued at the end of all UI operations. You can also pass a parameter for the timeinterval (around 4 ms) so that browsers with a slower JS engine can also perform smoothly.
...
var i = 0;
var timer = setInterval(function() {
var tweet = jsonTweets[i++];
var optional_id = '_user_tweets';
$('#all-user-tweets').mustache('tweets_tweet', {
tweet: tweet,
optional_id: optional_id
});
configureTweetSentiment(tweet);
configureTweetView(tweet);
if(i === jsonTweets.length){
clearInterval(timer);
}
}, 4); //Interval between loading tweets
...
NOTE
The solution is based on the following assumptions -
You are manipulating the dom with the configureTweetSentiment and the configureTweetView methods.
Ideally the solution provided above would not be the best solution. Instead you should create all html elements first in javascript only and at the end append the final html string to a div. You would see a drastic change in performance (Seriously!)
You don't want to use web workers because they are not supported in old browsers. If that's not the case and you are not manipulating the dom with the configure methods then web workers are the way to go for data intensive operations.

Javascript: Suppress "Stop running this script?", or how to use setTimeout?

I'm building a js library that reads binary files, including zip files.
Because there's no direct native support for arrays of binary data, when the zip files get large, there's a lot of copying that has to go on (See my other question for details).
This results in a "Stop Running this script?" alert. Now, I know this can happen if there's an infinite loop, but in my case, it's not an infinite loop. It's not a bug in the program. It just takes a loooooong time.
How can I suppress this?
This message is for security reason enabled, because otherwise you could simply block the users browser with a simple never ending loop. I think there no way to deactivate it.
Think about splitting you processing into serval parts, and schedule them via setTimeout, this should surpress the message, because the script is now not running all the time.
You could divide the process into increments, then use setTimeout to add a small delay.
In IE (and maybe Firefox too), the message is based on the number of statements executed, not the running time. If you can split some of the processing into a separate function, and defer it with setTimeout, I believe that it won't count toward the limit.
...answering my own question, so I could post the code I used.
The main issue was, I was reading the entire contents of a file, with a readToEnd() method, which actually reads one byte at a time. When reading a large file, it took a looooong time. The solution was to read asynchronously, and in batches.
This is the code I used:
readToEndAsync : function(callback) {
_state = "";
var slarge = "";
var s = "";
var txtrdr = this;
var readBatchAsync = function() {
var c = 0;
var ch = txtrdr.readChar();
while(ch != null)
{
s += ch;c++;
if(c > 1024)
{
slarge += s;
s = "";
break;
}
ch = txtrdr.readChar();
}
if (ch!=null){
setTimeout(readBatchAsync, 2);
}
else {
callback(slarge+s);
}
};
// kickoff
readBatchAsync();
return null;
},
And to call it:
textReader.readToEndAsync(function(out){
say("The callback is complete");
// the content is in "out"
});
I believe this feature is specific to Firefox and/or other browsers, and it has nothing to do with the javascript language itself.
As far as I know you (the programmer) have no way of stopping it in your visitors' browser.

Categories

Resources