在没有 setTimeout 的情况下等待定义值?
Wait for value to be defined without setTimeout?
我正在从某处获取一个值并想在本地使用它(使用 lodash):
const setting = _.get(this.settings, 'options');
this.settings.options
在别处设置,根据环境不同,this.settings.options
可能未定义。在那种情况下,我可以这样做:
const set = (setting) => {
...
...
};
const getThing = () => {
setTimeout(() => {
const setting = _.get(this.settings, 'options');
return setting ? set(setting) : getThing();
}, 1000);
};
getThing();
这使用了一个setTimeout
函数等待1秒等待this.settings.options
在那个时间被设置,如果还没有设置,setTimeout
函数调用自己来检查一个第二个。之后,它继续使用获取的数据执行 set()
函数。这似乎每次都有效,但如果我能一直检查这个值直到它在没有计时器的情况下被定义,那就太好了。我不确定这是否可能?
我一直在尝试实现 promise 或使用 async / await 来执行此操作,但我看到的示例似乎也使用了 setTimeout
s,并且解决方案最终看起来更加复杂.其中,我主要关注 this answer。无论如何,我在使用 async / await 执行此操作时遇到了问题,并且将不得不继续进行故障排除。
有没有办法在不使用 setTimeout
或 setInterval
的情况下等待定义此值?
遗憾的是,没有直接的方法。
如果你可以变异this.settings
(而且this.settings.options
至少是可配置的),那么你可以定义一个setter,然后等待它被触发。
这通常是一个丑陋的模式(只有在没有其他办法时才使用它),但仍然比定期检查 属性 是否存在要好。
另外注意只有当设置.options
的神秘代码使用[[Set]]
(即obj.prop = value
或Reflect.set
),而不是 [[Define]]
(即 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)
}
并且,您现在可以轻松地将其重写为使用 Promise
的通用函数(因此支持 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)
})
我正在从某处获取一个值并想在本地使用它(使用 lodash):
const setting = _.get(this.settings, 'options');
this.settings.options
在别处设置,根据环境不同,this.settings.options
可能未定义。在那种情况下,我可以这样做:
const set = (setting) => {
...
...
};
const getThing = () => {
setTimeout(() => {
const setting = _.get(this.settings, 'options');
return setting ? set(setting) : getThing();
}, 1000);
};
getThing();
这使用了一个setTimeout
函数等待1秒等待this.settings.options
在那个时间被设置,如果还没有设置,setTimeout
函数调用自己来检查一个第二个。之后,它继续使用获取的数据执行 set()
函数。这似乎每次都有效,但如果我能一直检查这个值直到它在没有计时器的情况下被定义,那就太好了。我不确定这是否可能?
我一直在尝试实现 promise 或使用 async / await 来执行此操作,但我看到的示例似乎也使用了 setTimeout
s,并且解决方案最终看起来更加复杂.其中,我主要关注 this answer。无论如何,我在使用 async / await 执行此操作时遇到了问题,并且将不得不继续进行故障排除。
有没有办法在不使用 setTimeout
或 setInterval
的情况下等待定义此值?
遗憾的是,没有直接的方法。
如果你可以变异this.settings
(而且this.settings.options
至少是可配置的),那么你可以定义一个setter,然后等待它被触发。
这通常是一个丑陋的模式(只有在没有其他办法时才使用它),但仍然比定期检查 属性 是否存在要好。
另外注意只有当设置.options
的神秘代码使用[[Set]]
(即obj.prop = value
或Reflect.set
),而不是 [[Define]]
(即 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)
}
并且,您现在可以轻松地将其重写为使用 Promise
的通用函数(因此支持 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)
})