I was going through the link https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Your_second_WebExtension.
I could not understand the keyword then() in the choose_beast.js script. I know it is something related to promises in javascript. Can you explain in simple language promises and use of then in this context?
Let us compare synchronous and asynchronous code.
Looking at a normal synchronous code:
let a = Date.now();
let b = a * 3;
a is set before b is set and it is available for the next line to be used
Looking at an asynchronous code:
let a = someAsyncFuntion();
let b = a * 3; // runs into error
a is NOT set before b is set and it is NOT available for the next line to be used, therefore it results in error.
The someAsyncFuntion() is queued to run when the next process is available. The parser moves to let b = a * 3; but here the a is not set yet, so there would be an error.
I simple words, in Promise the function is queued to run asynchronously. Therefore, then() is when it has done it.
Looking at the example on above page:
var gettingActiveTab = browser.tabs.query({active: true, currentWindow: true});
gettingActiveTab.then((tabs) => { browser.tabs.sendMessage(tabs[0].id, {beastURL: chosenBeastURL}); });
browser.tabs.query() does not run immediately and does not get results immediately. Therefore, we write the code so that when it gets the result then() do something.
// query tabs asynchronously
var gettingActiveTab = browser.tabs.query({.....});
// once got the result THEN do something
gettingActiveTab.then( /* do something */ );
I hope that helps.
Related
Trying to learn RxJs, and I found what looks like a nice tutorial on that topic at https://www.learnrxjs.io.
I'm going through their primer section, and I am not clear on what the return statement in the pipe() function actually does or what it means. These are a couple of screen shots from their tutorial:
In traditional programming, I've always understood a return statement to be an exit - if function A calls function B, and function B has the line return 1, then control goes back to function A.
Is that what happens here? If so, in either of these two examples, where am I returning to???
Or what if I don't want to return anywhere but act on the data immediately? For example, in the error handling example, instead of return makeRequest..., I want to do something like const result = makeRequest.... Can I do that?
In general I'm having some conceptual difficulties around all the returns I've seen used with observables, and any help in explaining what they do/are would be appreciated. So would any other tutorial sites on RxJs.
These are all very similar constructs in javascript
function adder0(a,b){
return a + b
}
const adder1 = (a,b) => {
return a + b
}
const adder2 = (a,b) => a + b
console.log(adder0(3,7)) // 10
console.log(adder1(3,7)) // 10
console.log(adder2(3,7)) // 10
lets re-write the code from that example but with explicit function definitions (instead of arrow syntax).
function maker(value){
return makeRequest(value).pipe(
catchError(handleError)
);
}
function actioner(value){
// take action
}
source.pipe(
mergeMap(maker)
).subscribe(actioner)
The thing to notice is that you never actually call these functions. RxJS does that for you. You give them a function and they'll call it when they're good and ready based on the spec for a given operator.
I have made a for loop who call a web worker to highlight code inside code tag
I have made this loop, this call my worker and do the job.
highlightBase: ->
codes = document.getElementsByClassName('hljs')
if (codes)
for code in codes
HighlightWorker = new Worker('/js/highlight_worker.js')
HighlightWorker.onmessage = (event) ->
code.innerHTML = event.data
HighlightWorker.postMessage(code.textContent)
This is working well but I need to stop this loop until the worker is done.
Is this possible to stop this loop and continue it after or I need to add some timeOut ?
I am not very familiar very coffeeScript but this might give you an idea.
Stoping a for loop is not possible. There are generator functions for that lazy evaluation purposes. However although you could use, i don't think you need generators here. Instead i guess promises could be very handy. You might use Promise.all(). But first you have to create a utility function to return a promise when you instantiate a worker.
function postMessageToWorker(worker,message){
var p = new Promise((resolve,reject) => worker.onmessage = resolve);
worker.postMessage(message);
return p;
}
var proms = [];
if (codes)
for (var code of codes)
proms.push(postMessageToWorker(new Worker('/js/highlight_worker.js'), code.textContent));
Promise.all(proms).then(a => a.forEach((e,i) => codes[i].innerHTML = e.data));
Here is a plunker code for you to play.
Why do you need to stop the loop?
It looks like you are trying to do synchronous tasks, meaning the workers do their job one after the other.
But the whole thing about workers is that they are asynchronous...
I guess if you want your code to work synchronously, you need to do something like that:
highlightBase: ->
codes = document.getElementsByClassName('hljs')
if (codes)
for code in codes
code.innerHTML = function_that_was_before_made_by_worker()
And that it is...
I am wondering whether the following is defined behavior per the Promise specification:
var H = function (c) {
this.d_p = Promise.resolve();
this.d_c = c;
};
H.prototype.q = function () {
var s = this;
return new Promise(function (resolve) {
s.d_p = s.d_p.then(function () { // (1)
s.d_c({
resolve: resolve
});
});
});
};
var a,
h = new H(function (args) { a = args; }),
p;
Promise.resolve()
.then(function () {
p = h.q();
})
.then(function () { // (2)
a.resolve(42);
return p;
});
The question is whether it's guaranteed that the then callback marked (1) is called before the then callback marked (2).
Note that both promises in question are instantly resolved, so it seems to me like the (1) then callback should be scheduled as part of calling h.q(), which should be before the promise used to resolve (2) is resolved, so it should be before (2) is scheduled.
An example jsfiddle to play about with: https://jsfiddle.net/m4ruec7o/
It seems that this is what happens with bluebird >= 2.4.1, but not prior versions. I tracked the change in behavior down to this commit: https://github.com/petkaantonov/bluebird/commit/6bbb3648edb17865a6ad89a694a3241f38b7f86e
Thanks!
You can guarantee that h.q() will be called before a.resolve(42); is called because chained .then() handlers do execute in order.
If you were asking about code within h.q(), then s.d_p.then() is part of a completely different promise chain and promise specifications do not provide ordering for separate promise chains. They are free to execute with their own asynchronous timing. And, in fact, I've seen some differences in the execution of independent promise chains in different Javascript environments.
If you want to direct the execution order between two independent promise chains, then you will have to link them somehow so one operation does not run until some other operation has completed. You can either link the two chains directly or you can do something more complicated involving an intermediate promise that is inserted into one chain so it blocks that chain until it is resolved.
You may find this answer useful What is the order of execution in javascript promises which provides a line by line analysis of execution order of both chained and independent promises and discusses how to make execution order predictable.
This is my JavaScript code.
function postFile(){
var obj=new Object();
obj.category=document.getElementsByName("gtitle")[0].value;
obj=obj.stringify(obj);
sendDetails("http://localhost:8080/Megabizz/webapi/gallery", obj);
var r;
ajaxRequest.onreadystatechange = function(){
if(ajaxRequest.readyState == 4){
r=new Object(JSON.parse(ajaxRequest.responseText));
console.log(r.status);
}
};
//r not accessible here
}
In the function postFile(), I have a declared a variable r now I am manipulating this r using ajaxRequest object.
Now when I am trying to access this r outside the function onreadystatechange(),
I am getting an error that "r is undefined".
I think that the function onreadystatechange() is declaring a new variable r instead of manipulating r declared above the onreadystatechange() function.
Tell me the way to overcome this problem.
//Another problem
var x;
function x(){
x=document.getElementByID("upload-buton");
}
function y(){
x.value='some text';
}
In this case, the value of x which I am setting in function y() does not remain same for the function x().
I am getting an error "cannot set property value for undefined".
Please figure out the cause behind this error.
Ajax (Asynchronous JavaScript and XML) makes your code Asynchronous. That means that not everything in your code happens in a straightforward manner (the code might not be executed in the order it is written).
For basic understanding async code see a tutorial Event-Based Programming: What Async Has Over Sync.
ajaxRequest.onreadystatechanges fires on state change event. After that, you are comparing ajaxRequest.readyState, which means that however r variable is always accessible, it will be changed only on 4: request finished and response is ready and will only be available after the completion of the Ajax request. Javascript will not wait for the Ajax request to finish.
A solution strongly depends on further actions you wish to do with r variable.
I am wondering if there's a way to create a promise chain that I can build based on a series of if statements and somehow trigger it at the end. For example:
// Get response from some call
callback = (response) {
var chain = Q(response.userData)
if (!response.connected) {
chain = chain.then(connectUser)
}
if (!response.exists) {
chain = chain.then(addUser)
}
// etc...
// Finally somehow trigger the chain
chain.trigger().then(successCallback, failCallback)
}
A promise represents an operation that has already started. You can't trigger() a promise chain, since the promise chain is already running.
While you can get around this by creating a deferred and then queuing around it and eventually resolving it later - this is not optimal. If you drop the .trigger from the last line though, I suspect your task will work as expected - the only difference is that it will queue the operations and start them rather than wait:
var q = Q();
if(false){
q = q.then(function(el){ return Q.delay(1000,"Hello");
} else {
q = q.then(function(el){ return Q.delay(1000,"Hi");
}
q.then(function(res){
console.log(res); // logs "Hi"
});
The key points here are:
A promise represents an already started operation.
You can append .then handlers to a promise even after it resolved and it will still execute predictably.
Good luck, and happy coding
As Benjamin says ...
... but you might also like to consider something slightly different. Try turning the code inside-out; build the then chain unconditionally and perform the tests inside the .then() callbacks.
function foo(response) {
return = Q().then(function() {
return (response.connected) ? null : connectUser(response.userData);
}).then(function() {
return (response.exists) ? null : addUser(response.userData);//assuming addUser() accepts response.userData
});
}
I think you will get away with returning nulls - if null doesn't work, then try Q() (in two places).
If my assumption about what is passed to addUser() is correct, then you don't need to worry about passing data down the chain - response remains available in the closure formed by the outer function. If this assumption is incorrect, then no worries - simply arrange for connectUser to return whatever is necessary and pick it up in the second .then.
I would regard this approach to be more elegant than conditional chain building, even though it is less efficient. That said, you are unlikely ever to notice the difference.