Javascript ES6承诺-如果不使用延迟,我如何保证最终访问React componentDidMount函数期间实例化的对象?
提前谢谢大家 我第一次使用ES6 native promises(在过去,我使用过Q或Angular的$Q服务)。我有一个问题可以通过使用延迟的方法轻松解决,我惊讶地发现ES6承诺没有使用它们 我还惊讶地发现,在博客上有大量人提到使用延迟作为反模式。即使在读了几篇谴责其使用的博客后,我仍然不明白为什么——他们的例子大多是我从一开始就不会使用延期的地方,所以也许我遗漏了一些东西(并且不介意解释为什么它们作为旁白不好)。但是为了保持在最佳实践的范围内,我试图找出如何解决一些问题,而不需要引入支持它们的库,我被卡住了 我正在使用OpenLayers库在我的React/Redux应用程序中创建一个映射。创建地图对象时,OpenLayers需要一个DOM元素来放置地图。因此,在安装组件之前,我无法实例化OpenLayers映射。没关系,componentDidMount有一个生命周期挂钩 我遇到的问题是,我需要将该映射对象公开给其他类,而这些类的代码需要等到创建映射后才能运行 通过延迟,我可以相当简单地处理此问题,如下所示:Javascript ES6承诺-如果不使用延迟,我如何保证最终访问React componentDidMount函数期间实例化的对象?,javascript,reactjs,ecmascript-6,promise,q,Javascript,Reactjs,Ecmascript 6,Promise,Q,提前谢谢大家 我第一次使用ES6 native promises(在过去,我使用过Q或Angular的$Q服务)。我有一个问题可以通过使用延迟的方法轻松解决,我惊讶地发现ES6承诺没有使用它们 我还惊讶地发现,在博客上有大量人提到使用延迟作为反模式。即使在读了几篇谴责其使用的博客后,我仍然不明白为什么——他们的例子大多是我从一开始就不会使用延期的地方,所以也许我遗漏了一些东西(并且不介意解释为什么它们作为旁白不好)。但是为了保持在最佳实践的范围内,我试图找出如何解决一些问题,而不需要引入支持它们
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
,并同意这将是一种黑客行为。如果您能为这种情况找到更好的解决方案,请告诉我们。我认为这解决了我的两个问题。我没有正确地考虑“解决”。我看着你们在现场编辑你们的回答,因为你们想得更多,我感谢你们对我的问题给予更多的思考。至于这是否是一种可怕的模式