[英]How to avoid including a redundant promise implementations in a browser JavaScript library?
I am writing a JavaScript library for the browser that currently exposes functions that take callback arguments.我正在为浏览器编写一个 JavaScript 库,该库当前公开采用回调参数的函数。 For the next version of the library I would like to have those functions return promises instead.
对于库的下一个版本,我希望这些函数返回承诺。 However, I haven't figured out a good way to know which flavor of promises (if any) exist in the client app.
但是,我还没有想出一个好方法来了解客户端应用程序中存在哪种承诺(如果有)。
I could say my library requires the use of a Promise polyfill, but promise libraries like Bluebird, Q, and RSVP don't always create a Promise
global.我可以说我的库需要使用 Promise polyfill,但是像 Bluebird、Q 和 RSVP 这样的
Promise
库并不总是创建一个Promise
全局Promise
。 So then apps that depend on my library would have to either add a redundant promise polyfill, or expose their library's implementation to the global namespace like因此,依赖于我的库的应用程序将不得不添加一个冗余的承诺 polyfill,或者将其库的实现公开给全局命名空间,例如
import RSVP from 'rsvp';
window.Promise = RSVP.Promise
I'm having a hard time finding any examples of a good way to avoid including redundant promise implementations.我很难找到避免包含冗余承诺实现的好方法的任何示例。 The closest thing I've seen is https://github.com/agershun/alasql/blob/develop/src/18promise.js , which will use the app's global promise if it exists, but also includes an inlined copy of the es-6-promise polyfill.
我见过的最接近的是https://github.com/agershun/alasql/blob/develop/src/18promise.js ,它将使用应用程序的全局承诺(如果存在),但还包括 es 的内联副本-6-promise polyfill。
There are basically three situations you have to deal with:基本上有三种情况你必须处理:
1. There is a global Promise
already defined and the caller of your library does not provide a different one. 1. 已经定义了一个全局
Promise
并且您的库的调用者没有提供不同的Promise
。 In that case, you should be able to detect the existing global implementation and just use it without any other intervention.在这种情况下,您应该能够检测现有的全局实现并直接使用它而无需任何其他干预。 This is what the world looks like in modern browsers today and into the future so this is a good case to handle well.
这就是当今和未来现代浏览器中世界的样子,因此这是一个很好处理的案例。
2. There is no global Promise
defined and the caller of your library does not provide one to you. 2. 没有定义全局
Promise
并且你的库的调用者没有提供给你。 If you intend to support this case, then you need to either have a polyfill already built-in or be able to dynamically load one.如果您打算支持这种情况,那么您需要已经内置了一个 polyfill,或者能够动态加载一个 polyfill。 I would recommend dynamically loading Bluebird since it is 100% ES6 compatible, is available via a CDN (easy to dynamically load), dynamically loading would avoid duplicate implementations and Bluebird has many other useful benefits too .
我建议动态加载 Bluebird,因为它 100% 兼容 ES6,可通过 CDN 获得(易于动态加载),动态加载将避免重复实现,并且 Bluebird 也有许多其他有用的好处。
3. The caller of your library wants to provide you a specific promise implementation that they have already loaded. 3. 你的库的调用者想要为你提供他们已经加载的特定承诺实现。 This other implementation may or may not be defined as the global
Promise
.这个其他实现可能会也可能不会被定义为全局
Promise
。 In this case, you would usually have an optional setting
or init
for your library that allows the developer to tell you which promise library to use before any of your other API functions are called.在这种情况下,您通常会为您的库
setting
一个可选setting
或init
,以允许开发人员在调用任何其他 API 函数之前告诉您要使用哪个 Promise 库。 You store that away in your own storage and just use that everywhere in your code.您将其存储在您自己的存储中,然后在代码中的任何地方使用它。
You can be very developer-friendly and flexible by supporting all three of these options.通过支持所有这三个选项,您可以对开发人员非常友好和灵活。 It requires only a little code on your part.
它只需要您编写少量代码。 First, you offer an API for setting which Promise implementation to use and you store that implementation in your module and you use that everywhere.
首先,您提供一个 API 来设置要使用的 Promise 实现,并将该实现存储在您的模块中,并在任何地方使用它。 Then, if that API is not called to set a specific implementation, you detect if the global
Promise
is there.然后,如果未调用该 API 来设置特定实现,则您会检测全局
Promise
是否存在。 If it is, you use it.如果是,你就使用它。 If not, then you dynamically load Bluebird from a CDN.
如果没有,那么您可以从 CDN 动态加载 Bluebird。 That's a fairly small amount of code for very flexible and developer-friendly support and, going forward, it's nice and simple for everyone (you will just default to the build-in ES6 Promise implementation).
对于非常灵活和对开发人员友好的支持,这是相当少量的代码,而且,今后,它对每个人来说都很好且简单(您将默认使用内置的 ES6 Promise 实现)。
If you want the bare minimum (and small) ES6 polyfill, there are several available.如果你想要最小的(和小的)ES6 polyfill,有几个可用的。 One I've seen regularly is this one which comes from the RSVP folks, but is designed to be as small as possible 100% compatible ES6 polyfill with no extra features (only 2.6k).
我经常看到的一个是来自 RSVP 的人,但被设计为尽可能小,100% 兼容 ES6 polyfill,没有额外的功能(只有 2.6k)。
As an even simpler alternative for you (but less developer-friendly), you could put more of the burden on the developer using your library and just declare that your library requires that a global Promise
be defined before initializing your library.作为对您来说更简单的替代方案(但对开发人员不太友好),您可以为使用您的库的开发人员增加更多的负担,只需声明您的库要求在初始化您的库之前定义一个全局
Promise
。 In that case, the developer using your library would have to get their own Promise polyfill if they wanted to use your library with older browsers.在这种情况下,使用您的库的开发人员如果想在较旧的浏览器中使用您的库,则必须获得自己的 Promise polyfill。 This obviously puts more of the work back on the developer using yourlibrary and you'd have to check for the presence of a global
Promise
and, if not present, then throw an exception upon initialization.这显然将更多的工作交给使用您的库的开发人员,您必须检查全局
Promise
的存在,如果不存在,则在初始化时抛出异常。 I personally would not recommend this alternative.我个人不推荐这种替代方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.