javascript - ES6 Promises - 在不使用延迟的情况下,我如何保证最终访问在 React componentDidMount 函数期间实例化的对象?

标签 javascript reactjs ecmascript-6 promise q

提前谢谢大家。

我是第一次使用 ES6 原生 promise (过去,我使用过 Q 或 Angular 的 $q 服务)。我有一个问题可以通过使用 deferred 轻松解决,并且惊讶地发现 ES6 promises 不使用它们。

我更惊讶地发现博客上有很多人将 deferred 的用法称为反模式。即使在阅读了一些谴责使用 deferred 的博客之后,我仍然不太明白为什么 - 他们的例子大部分都是我从一开始就不会使用 deferred 的地方,所以也许我遗漏了一些东西(并且不介意解释顺便说一下为什么它们不好)。但是为了保持在最佳实践的范围内,我试图弄清楚如何在不引入支持它们的库的情况下解决问题,但我被困住了。

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

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

有了 deferred,我可以相当简单地处理这个问题,如下所示:

const deferred = Q.defer();

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

export getMap => deferred.promise

但是对于 ES6 promise ,我被卡住了。

我无法在 componentDidMount 类之外实例化 promise ,因为它会立即触发。

如果我在 componentDidMount 函数的范围内实例化一个 promise(或使用 Promise.resolve,因为我的代码是同步的),则该 promise 超出了 getMap 函数的范围。

如果我在 componentDidMount 范围之外声明但不实例化 promise 对象,则 getMap 将返回 undefined 直到 componentDidMount 执行,首先破坏了拥有 promise 的意义。

作为最后的想法,我没有将 map 置于 Redux 状态,因为 OpenLayers map 是高度可变的并且做自己的事情,如果我将 map 放在那里,它会破坏 Redux 对不变性的 promise ......所以我已经放弃了 Redux 解决方案。在 Redux 状态上抛出某种 bool 值,比如“mapAvailable”,感觉就像一个 hack。我可能可以做到这一点,但它会引入许多次要问题。

那我错过了什么?我是在一个极端情况下,延期确实是正确的答案,还是我只是没有看到显而易见的东西?

再次感谢您的宝贵时间。

最佳答案

I was further surprised to discover a large number of people on blogs referring to the usage of deferred as an anti-pattern.

您似乎指的是 deferred antipattern这里是关于 deferred 的特定用法 - 它并没有说 deferred 是一种反模式。

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

I can't instantiate the promise outside of the componentDidMount class because it will fire immediately.

为什么要立即开火?只是不要那样做。你甚至可以把它包裹在类里面:

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);
  }
  …
}

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

关于javascript - ES6 Promises - 在不使用延迟的情况下,我如何保证最终访问在 React componentDidMount 函数期间实例化的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47417550/

相关文章:

javascript - 我可以单击()按钮,但看不到innerHTML/length。这是怎么回事? ( Node JS)

javascript - React Native Redux 不改变状态我不明白为什么

javascript - 映射到数组后创建动态对象键

javascript - 将代码从函数式 React hook 转换为类组件

javascript - React Native 中的 ".eslintrc.js"是什么?

javascript - 对象 es6 的条件解构数组

javascript - "Unlink"数据库回显结果

javascript - 如何使从书签加载的JS文件的缓存失效?

javascript - 错误: Uncaught [TypeError: Cannot read property 'x' of undefined Jest react testing

javascript - 警告 : React does not recognize the X prop on a DOM element