等待没有setTimeout的值被定义?

时间:2019-09-10 22:49:41

标签: javascript ecmascript-6 async-await es6-promise

我要从某个地方获取一个值,并想在本地使用它(使用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进行操作时遇到了麻烦,将不得不继续对它进行故障排除。

是否有一种方法可以等待不使用setTimeoutsetInterval来定义此值?

1 个答案:

答案 0 :(得分:1)

不幸的是,没有简单的方法可以做到这一点。

如果您可以更改this.settings(并且this.settings.options至少是可配置的),则可以定义一个setter,并等待其触发。

这通常是一个丑陋的模式(仅在没有其他方法的情况下才使用它),但比定期检查属性的存在还是要好。

请注意,这仅在设置.options的神秘代码使用[[Set]](即obj.prop = valueReflect.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)
})