如何避免在浏览器 JavaScript 库中包含冗余的 Promise 实现?
Posted
技术标签:
【中文标题】如何避免在浏览器 JavaScript 库中包含冗余的 Promise 实现?【英文标题】:How to avoid including a redundant promise implementations in a browser JavaScript library? 【发布时间】:2017-07-02 00:10:42 【问题描述】:我正在为当前公开接受回调参数的函数的浏览器编写一个 javascript 库。对于库的下一个版本,我希望这些函数返回 Promise。但是,我还没有找到一个很好的方法来了解客户端应用程序中存在哪种类型的 Promise(如果有的话)。
我可以说我的库需要使用 Promise polyfill,但是像 Bluebird、Q 和 RSVP 这样的 Promise 库并不总是创建一个 Promise
全局。因此,依赖于我的库的应用程序将不得不添加一个冗余的 promise polyfill,或者将其库的实现暴露给全局命名空间,例如
import RSVP from 'rsvp';
window.Promise = RSVP.Promise
我很难找到任何避免包含冗余承诺实现的好方法的示例。我见过的最接近的东西是https://github.com/agershun/alasql/blob/develop/src/18promise.js,如果它存在,它将使用应用程序的全局承诺,但也包括 es-6-promise polyfill 的内联副本。
【问题讨论】:
你可以要求你的调用者将一个 Promise 实现传递给你的 lib 的构造函数,或者有一个全局的MyLib.init(PromiseConstructor)
,只有在需要 polyfill 时才需要调用
【参考方案1】:
基本上你需要处理三种情况:
1.已经定义了一个全局Promise
,并且您的库的调用者没有提供不同的。在这种情况下,您应该能够检测到现有的全局实现并直接使用它而无需任何其他干预。这就是当今和未来现代浏览器中世界的样子,所以这是一个很好的处理方式。
2。没有定义全局 Promise
并且你的库的调用者没有为你提供一个。 如果你打算支持这种情况,那么你需要已经内置了一个 polyfill 或者能够动态地加载一个。我建议动态加载 Bluebird,因为它 100% 兼容 ES6,可通过 CDN 获得(易于动态加载),动态加载可以避免重复实现,并且 Bluebird 有 many other useful benefits too。
3.您的库的调用者希望为您提供他们已经加载的特定承诺实现。此其他实现可能定义为也可能不定义为全局 Promise
。在这种情况下,您的库通常会有一个可选的setting
或init
,它允许开发人员在调用任何其他 API 函数之前告诉您要使用哪个承诺库。您将其存储在自己的存储中,然后在代码中的任何地方使用它。
通过支持所有这三个选项,您可以对开发人员非常友好和灵活。它只需要你的一点代码。首先,您提供一个 API 来设置要使用的 Promise 实现,并将该实现存储在您的模块中,然后在任何地方使用它。然后,如果没有调用该 API 来设置特定的实现,您将检测全局 Promise
是否存在。如果是,你就用它。如果没有,那么您从 CDN 动态加载 Bluebird。对于非常灵活和对开发人员友好的支持来说,这是相当少量的代码,而且今后,它对每个人来说都很好且简单(您将默认使用内置的 ES6 Promise 实现)。
如果你想要最简单(和小型)的 ES6 polyfill,有几个可用的。我经常看到的一个是this one,它来自 RSVP 人员,但被设计为尽可能小,100% 兼容 ES6 polyfill,没有额外的功能(只有 2.6k)。
作为对您来说更简单的替代方案(但对开发人员不太友好),您可以将更多的负担交给使用您的库的开发人员,只需声明您的库需要在初始化您的库之前定义一个全局 Promise
.在这种情况下,使用你的库的开发人员如果想在旧版浏览器中使用你的库,就必须获得他们自己的 Promise polyfill。这显然将更多的工作交给了使用 yourlibrary 的开发人员,您必须检查全局 Promise
是否存在,如果不存在,则在初始化时抛出异常。我个人不会推荐这种替代方案。
【讨论】:
以上是关于如何避免在浏览器 JavaScript 库中包含冗余的 Promise 实现?的主要内容,如果未能解决你的问题,请参考以下文章
浏览器控制台 - 如何在每个页面重定向中包含javascript代码?
如何在另一个 javascript 文件中包含 jquery [重复]