How can I retrieve some variables in another method - javascript

I want to know the best way to retrieve the variable tag and msgCommit in the another method
public async run(commande){
...
}
public async test(){
const tag = 123
const msgCommit = await this.run('git rev-parse ' + tag )
...
}
public async test2(){
// How can I retrieve tag and msgCommit
...
}
Thanks in advance for your help :)

You're variables within test() have blocked-scope (as they're defined using const) and so cannot be accessed outside your function unless you return them. To do so, you need to wrap them in some sort of container such as an array:
public async test(){
const tag = 123
const msgCommit = await this.run('git rev-parse ' + tag )
return [tag, msgCommit];
}
And now, you can access your variables tag and msgCommit inside your test2() method by calling test() within it.
However, all async functions will return a Promise implicitly (with the original return set as the resolve), and so, when you call test() you will get a Promise. This means your array will be wrapped within this Promise. To "extract" your array from the Promise, you can await (or use .then() on) the promise to get its contents once it has resolved:
public async test2() { // `async` so we can use `await` inside this method
// How can I retrieve tag and msgCommit
const [tag, msgCommit] = await test(); // destructure your array and store the elements as variables
console.log(tag, msgCommit);
}

Related

How to call an async function inside an if statement?

To keep variables in background.js in chrome extension I need to reinitiate some global variables, and I meet some difficulties.
Here is the code(fiddle) that I want to use to illustrate the problem:
var temp = null;
function someTimeConsumingThing() {
return new Promise(function(resolve,reject) {
setTimeout(resolve, 2000);
temp = 10;
})
}
async function a(){
if(temp==null){
await someTimeConsumingThing();
}
return temp
}
function b(){
let localTemp = a();
console.log(localTemp);
}
b();
In the above code snippet, the temp variable would sometimes be null and to ensure that temp is not null I should call an async function someTimeConsumingThing. As we can see, the console.log outputs a Promise rather than 10; and an error would occur if I add await before a():
Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules"
How can I tackle this problem? I have read many related but unhelpful answers here and I don't know how to optimize my search input to get the most related question. This problem would be very naive for JS experts and there are certainly available answers on this site.
You forgot to use await when calling a(), which means you printed the returned promise instead of the async result of a(). The containing function therefore also needs to be async, since it contains an await call.
Note that it's good practice to mark the someTimeConsumingThing function as async, because it returns a Promise.
Also note that your someTimeConsumingThing function sets temp to 10 immediately, and then delays until returning. I've rewritten it so it only sets temp to 10 after the delay has completed.
let temp = null;
async function someTimeConsumingThing() {
return new Promise(resolve => {
setTimeout(()=>{
temp = 10;
resolve();
}, 2000);
})
}
async function a(){
if(temp==null){
await someTimeConsumingThing();
}
return temp;
}
async function b(){
let localTemp = await a();
console.log(localTemp);
}
b();
A function that calls an async function and needs the result of that function, must in itself (by definition) be asynchronous.
Just change b so that it is an async function:
async function b(){
let localTemp = await a();
console.log(localTemp);
}

is const variable in javascript function initialized every time when it called or just once?

I'd like to code something like this.
function cokeDispencer(id) {
const dict = {1:"sprite", 2:"pepcy", ...} // Some JSON. It might be bigger.
return dict[id];
}
Of course, dict[id] is much simpler way to do the same, but I want put the dict object inside of function so that no other function can access to this dict object.
What I'm wondering is that the object dict is initialized everytime it called. As I know, function written in C/C++ initalize it's local variable everytime it called except static variable. If then, is there a way to initalize const variable just once like static variable C/C++?
Yes, you're creating a new dict object every time that function runs.
You can make an IIFE instead - a function that runs immediately and "closes" over the object and can return a function that accesses the desired property.
const cokeDispencer = (() => {
const dict = {1:"sprite", 2:"pepcy"} // Some JSON. It might be bigger.
return id => dict[id];
})();
console.log(cokeDispencer(1));
This is almost the same thing as
const dict = {1:"sprite", 2:"pepcy"} // Some JSON. It might be bigger.
const cokeDispencer = id => dict[id];
console.log(cokeDispencer(1));
except that the IIFE makes sure that only the cokeDispener function has access to the object.
If you want to create the object only the first time the function is called, and not before, you could use a pretty similar technique to assign to a variable scoped only to the function if needed.
const cokeDispencer = (() => {
let dict;
return (id) => {
if (!dict) {
dict = {1:"sprite", 2:"pepcy"} // Some JSON. It might be bigger.
}
return dict[id];
};
})();
console.log(cokeDispencer(1));

await with overloaded methods

I have an ES6 class hierarchy. All of the classes in the hierarchy implement a draw() method. Some implement it synchronously but some need this method to be async.
How can I call draw() correctly in this sort of setup?
Is it possible to find if the method being called is async and only then call await on it's result?
You could check if the draw() has a .then function since all promises will have to implement that. If it does, use async, else execute directly
Check this answer on how to determine a promise How do I tell if an object is a Promise?
if(draw.then) { // all async await functions wrap the return into promises. So, this should
const resolvedData = await draw(); // store the data if you need to get the value
else
draw()
I wanted to avoid having to decla(r)e 100 methods as async for the
sake of just the two that actually need it.
A function doesn't have to be async (ie: return a promise) to be awaited. A synchronous function can be awaited too. This means that if a promise is not returned by draw() (ie: your draw() method is synchronous), then the await will convert the returned value of draw() to a resolved promise which it then waits for and retrieves its value.
So, something like the following is possible:
function foo() { // returns a string
return "foo";
}
async function bar() { // implicitly returns a promise
return "bar";
}
(async function() {
const fooStr = await foo(); // foo() is synchronous, but can be `await`ed still
const barStr = await bar(); // bar() is asynchronous, and can be `await`ed
console.log(fooStr, barStr);
})();
With this in mind, you don't need to know if draw() is synchronous or not, instead, you can always await the draw() method, regardless of its return type.
You can check your function if it is async function by using Object.prototype.constructor.name.
var object = {
draw: async function() {}
}
var object1 = {
draw: function() {}
}
console.log(object.draw.constructor.name);
console.log(object1.draw.constructor.name);

Make an IIFE return variables for only some other IIFES

I was wondering if we can declare a variable in one IIFE and the return it but make it available for another specific IIFE? Here is an example!
So I have
const iife1 = (()=>{
const x = 10;
return x
})()
const iife2 = (()=>{/* MAKE X AVAILABLE ONLY IN THIS FUNCTION */})()
const iife3 = (()=>{/* HERE X CANNOT BE CALLED */})()
Maybe you would say just not to pass the variable x in the iif3 as an argument, but I was wondering if there is a conditional way we can achieve it when returning the variable from iif1, so the iif1 will know for which functions it returns its properties or methods before actually has returned!
My goal is to create an IIFE which in it I will declare all the variables that I am going to use in my project. Then for each variable, I want to have a proper condition so that when the IIFE with the variables returns the function has already decided in which scope will sent the variables for use! I don't know if this approach makes sense but as is always being said I am trying not to populate the global scope.
Codepen
One of the (probaby dozen) ways to achieve that is by using a Proxy.
First IIFE would create a proxy object through which you'd access its properties. After calling the revoke(), you will no longer be able to access any of the proxy's props.
As people have stated in their comments, there are probably much easier ways for you to achieve the wanted result, but you haven't presented the actual problem clearly.
const { proxy, revoke } = (() => {
const x = { test: 'test' };
const revocable = Proxy.revocable(x, {
get: (target, name) => name
});
return revocable;
})();
const test1 = (proxy => {
console.log('TEST 1', proxy.test);
})(proxy);
revoke();
const test2 = (proxy => {
console.log('TEST 2', proxy.test); // can't access
})(proxy);
Fiddle:
https://jsfiddle.net/ay92L1r6/6/
IIFEs can only use Global, Passed, or internal variables. You can't make something available to a function scope that isn't available to a second function in the same scope.
Passing variables is one way, but perhaps the more practical way in certain circumstances would be to just nest your IIFEs as needed
const iife2 = (() => {
const iife1 = (() => {
const x = 10;
return x
})()
console.log(iife1);
/*iife2 scope*/
})()
const iife3 = (() => { /* HERE X CANNOT BE CALLED */ })()
It is not necessary to use three IIFE, remember that as soon as your iife1 returns that value will be in the same scope of iife2 and iife3 thus you won't achieve your goal.
Your best bet is to declare iife2 and iife3 as normal functions and call them inside iife1 when some conditions are met and pass the variable that will create the scope of iife3 as argument.
this solution is more flexible and predictable than relying on the outer scope
const fn2 = function(x) {/* MAKE X AVAILABLE ONLY IN THIS FUNCTION */};
const fn3 = function() {/* HERE X CANNOT BE CALLED */};
(()=>{
const x = 10;
//your logic
fn2(x);
fn3();
})()

Why can't I access a returned function with the dot syntax

I though that once createFunction runs I'll have access to the inner function.
function createFunction() {
function printHello() {
return console.log("hello");
}
return printHello;
}
// Both of these return undefined
createFunction(printHello());
createFunction.printHello();
Any thoughts?
Proper syntax is:
createFunction()();
... or, a bit more wordy:
const returnedFunction = createFunction();
returnedFunction();
... as printHello name makes any sense only within createFunction, but its value is actually returned by that function. And yes, it's perfectly ok to place any number of () in sequence you want.
As a sidenote, returning the result of console.log('hello') makes little sense: logging itself is a side effect, no need to check its result.
I though that once createFunction runs I'll have access to the inner function.
No, you cannot access a variable that is inside of a function outside of it. If you call a function those variables exist, but you cannot access them. However if a value gets returned, you can work with the function call as if it would be that expression. In your case you return the function so you can access it as:
var print = createFunction();
print();
Or as a oneliner:
createFunction()();
In your code createFunction returns another function, so to execute inner function you must call inner function by appending () after return value of createFunction i.e createFunction()();
createFunction() give printHello = function definition
createFunction() () same as printHello**()**
Also if we simplify your code we can re-write as
function printHello() {
console.log("hello");
};
function createFunction() {
return printHello;
};
console.log("return value of: createFunction()");
console.log(createFunction());
console.log("return value of: createFunction() () --> printHello()");
createFunction()();

Categories