Javascript ES6承诺-如果不使用延迟,我如何保证最终访问React componentDidMount函数期间实例化的对象?

Javascript ES6承诺-如果不使用延迟,我如何保证最终访问React componentDidMount函数期间实例化的对象?,javascript,reactjs,ecmascript-6,promise,q,Javascript,Reactjs,Ecmascript 6,Promise,Q,提前谢谢大家 我第一次使用ES6 native promises(在过去,我使用过Q或Angular的$Q服务)。我有一个问题可以通过使用延迟的方法轻松解决,我惊讶地发现ES6承诺没有使用它们 我还惊讶地发现,在博客上有大量人提到使用延迟作为反模式。即使在读了几篇谴责其使用的博客后,我仍然不明白为什么——他们的例子大多是我从一开始就不会使用延期的地方,所以也许我遗漏了一些东西(并且不介意解释为什么它们作为旁白不好)。但是为了保持在最佳实践的范围内,我试图找出如何解决一些问题,而不需要引入支持它们

提前谢谢大家

我第一次使用ES6 native promises(在过去,我使用过Q或Angular的$Q服务)。我有一个问题可以通过使用延迟的方法轻松解决,我惊讶地发现ES6承诺没有使用它们

我还惊讶地发现,在博客上有大量人提到使用延迟作为反模式。即使在读了几篇谴责其使用的博客后,我仍然不明白为什么——他们的例子大多是我从一开始就不会使用延期的地方,所以也许我遗漏了一些东西(并且不介意解释为什么它们作为旁白不好)。但是为了保持在最佳实践的范围内,我试图找出如何解决一些问题,而不需要引入支持它们的库,我被卡住了

我正在使用OpenLayers库在我的React/Redux应用程序中创建一个映射。创建地图对象时,OpenLayers需要一个DOM元素来放置地图。因此,在安装组件之前,我无法实例化OpenLayers映射。没关系,componentDidMount有一个生命周期挂钩

我遇到的问题是,我需要将该映射对象公开给其他类,而这些类的代码需要等到创建映射后才能运行

通过延迟,我可以相当简单地处理此问题,如下所示:

const deferred = Q.defer();

const Foo = React.createClass({
  componentDidMount() {
    const map = new ol.Map(...);
    deferred.resolve(map);
  }
  ...
}

export getMap => deferred.promise
但是有了ES6的承诺,我就被卡住了

我无法在componentDidMount类之外实例化承诺,因为它将立即启动

如果我在componentDidMount函数的作用域内实例化一个承诺(或者使用promise.resolve,因为我的代码是同步的),那么该承诺就超出了getMap函数的作用域

如果我在componentDidMount的作用域之外声明但不实例化promise对象,则getMap将返回未定义的对象,直到componentDidMount执行为止,这就破坏了首先拥有promise的意义

最后一个想法是,我不会把地图放在Redux状态,因为OpenLayers地图是高度可变的,并且做自己的事情,如果我把地图放在那里,它会打破Redux对不变性的承诺。。。所以我放弃了Redux解决方案。在Redux状态上抛出某种布尔值,比如“mapavable”,感觉像是一种黑客行为。我或许可以做到这一点,但这会带来许多次要问题

那么我错过了什么?我是处在一个尊重才是正确答案的困境中,还是我只是看不到显而易见的东西

再次感谢您抽出时间

我还惊讶地发现,在博客上有大量人提到使用延迟作为反模式

您似乎提到了here,它是关于延迟的一种特定用法的,它并没有说延迟是一种反模式

尽管如此:-)您不需要任何延迟对象,
resolve
函数绝对足够了

我无法在
componentDidMount
类之外实例化承诺,因为它将立即启动

你为什么要马上开火?别那么做。你甚至可以把它包装在课堂上:

export const promise = new Promise(resolve => {
  const Foo = React.createClass({
    componentDidMount() {
      const map = new ol.Map(…);
      resolve(map);
    }
    …
  }
  … // do something with Foo here
});
但更可能的情况是,你会想这样做

let resolve;
export const promise = new Promise(r => {
  resolve = r;
});
export const Foo = React.createClass({
  componentDidMount() {
    const map = new ol.Map(…);
    resolve(map);
  }
  …
}
当然,请注意这是一个可怕的模式-您刚刚创建了一个全局的、静态的承诺,基本上是一个单例。当你的应用程序中可能包含的任何
Foo
组件被挂载时,就会解决这个问题。不要那样做。我建议将这个承诺放在组件的构造函数中,尽管我仍然不确定您到底需要它做什么

我还惊讶地发现,在博客上有大量人提到使用延迟作为反模式

您似乎提到了here,它是关于延迟的一种特定用法的,它并没有说延迟是一种反模式

尽管如此:-)您不需要任何延迟对象,
resolve
函数绝对足够了

我无法在
componentDidMount
类之外实例化承诺,因为它将立即启动

你为什么要马上开火?别那么做。你甚至可以把它包装在课堂上:

export const promise = new Promise(resolve => {
  const Foo = React.createClass({
    componentDidMount() {
      const map = new ol.Map(…);
      resolve(map);
    }
    …
  }
  … // do something with Foo here
});
但更可能的情况是,你会想这样做

let resolve;
export const promise = new Promise(r => {
  resolve = r;
});
export const Foo = React.createClass({
  componentDidMount() {
    const map = new ol.Map(…);
    resolve(map);
  }
  …
}

当然,请注意这是一个可怕的模式-您刚刚创建了一个全局的、静态的承诺,基本上是一个单例。当你的应用程序中可能包含的任何
Foo
组件被挂载时,就会解决这个问题。不要那样做。我建议将这个承诺放在组件的构造函数中,尽管我仍然不确定您到底需要它做什么。

您遇到的情况是,deferred可以很好地工作,但它们已经过时,这就是您发现博客中声明deferred作为反模式使用的原因

你可以看一看,这将给你更多的细节,延迟已过时


我认为同样的解决方案是
mapavable
,并同意这将是一种黑客行为。如果您找到了更好的解决方案,请告诉我们。

您所处的情况是,deferred可以正常工作,但它们已过时,这就是您找到将deferred用作反模式的博客的原因

你可以看一看,这将给你更多的细节,延迟已过时


我认为同样的解决方案是
mapavable
,并同意这将是一种黑客行为。如果您能为这种情况找到更好的解决方案,请告诉我们。

我认为这解决了我的两个问题。我没有正确地考虑“解决”。我看着你们在现场编辑你们的回答,因为你们想得更多,我感谢你们对我的问题给予更多的思考。至于这是否是一种可怕的模式