I'm grabbing a value from somewhere and wanting to use it locally (using lodash):
const setting = _.get(this.settings, 'options');
this.settings.options
is set somewhere else, and depending on the environment, this.settings.options
may be undefined. In that case, I can do something like:
const set = (setting) => {
...
...
};
const getThing = () => {
setTimeout(() => {
const setting = _.get(this.settings, 'options');
return setting ? set(setting) : getThing();
}, 1000);
};
getThing();
This uses a setTimeout
function to wait 1 second for this.settings.options
to be set in that time, and if it's not yet set, the setTimeout
function calls itself to check one second later. After that, it continues to the set()
function with the acquired data. This seems to work every time, but it would be really nice if I could keep checking for this value until it is defined without a timer. I'm not sure if that's possible?
I've been trying to implement either a promise or use async / await to do this, but the examples I've seen also seem to use setTimeout
s, and the solution ends up seemingly more complicated. Among others, I've mainly been looking at this answer. Regardless, I'm having trouble doing this with async / await and will have to continue troubleshooting that.
Is there a way to wait for this value to be defined without using a setTimeout
or setInterval
?
– Async Function-Based Promises: Use the “Await” Function For async function-based promises, you may add the “await” function to stop the function in javascript, until the promise is fulfilled, and then return the result value.
Use of setTimeout() function: In order to wait for a promise to finish before returning the variable, the function can be set with setTimeout(), so that the function waits for a few milliseconds. Use of async or await() function: This method can be used if the exact time required in setTimeout() cannot be specified.
Unfortunately, there is no straightforward way to do it.
If you can mutate this.settings
(and this.settings.options
is at least configurable), then you can define a setter, and wait for it to be triggered.
This is generally an ugly pattern (use it only if there's no other way), but still better than periodically checking the existence of a property.
Also note that this will work only if the mysterious code that sets .options
uses [[Set]]
(i.e., obj.prop = value
or Reflect.set
), and not [[Define]]
(i.e., Object.defineProperty
).
if(typeof this.settings.options==='undefined'){
//Define a setter
Object.defineProperty(this.settings, 'options', {
set: (value)=>{
//Remove setter, and transform to simple property
Object.defineProperty(this.settings, 'options', {value})
//Hypothetical function to be called with the result
doSomethingWithTheValue(value)
},
configurable: true,
enumerable: true
})
}else{
doSomethingWithTheValue(this.settings.options)
}
And, you can now easily rewrite this to a general function that uses Promise
s (and therefore supports async
/await
):
function getAsync(obj, prop){
return new Promise((resolve,reject)=>{
if(typeof obj[prop]==='undefined'){
Object.defineProperty(obj, prop, {
set: (value)=>{
Object.defineProperty(obj, prop, {value})
resolve(value)
},
configurable: true,
enumerable: true
})
}else{
resolve(obj[prop])
}
})
}
getAsync(this.settings,'options')
.then(doSomethingWithTheValue)
//or, async/await:
(async()=>{
const value=await getAsync(this.settings,'options')
doSomethingWithTheValue(value)
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With