# lib/goog/promise/thenable.js

1 | // Copyright 2013 The Closure Library Authors. All Rights Reserved.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS-IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | goog.provide('goog.Thenable');
16 |
17 |
18 |
19 | /**
20 | * Provides a more strict interface for Thenables in terms of
21 | * http://promisesaplus.com for interop with {@see goog.Promise}.
22 | *
23 | * @interface
24 | * @extends {IThenable<TYPE>}
25 | * @template TYPE
26 | */
27 | goog.Thenable = function() {};
28 |
29 |
30 | /**
31 | * Adds callbacks that will operate on the result of the Thenable, returning a
32 | * new child Promise.
33 | *
34 | * If the Thenable is fulfilled, the {@code onFulfilled} callback will be
35 | * invoked with the fulfillment value as argument, and the child Promise will
36 | * be fulfilled with the return value of the callback. If the callback throws
37 | * an exception, the child Promise will be rejected with the thrown value
38 | * instead.
39 | *
40 | * If the Thenable is rejected, the {@code onRejected} callback will be invoked
41 | * with the rejection reason as argument, and the child Promise will be rejected
42 | * with the return value of the callback or thrown value.
43 | *
44 | * @param {?(function(this:THIS, TYPE):
45 | * (RESULT|IThenable<RESULT>|Thenable))=} opt_onFulfilled A
46 | * function that will be invoked with the fulfillment value if the Promise
47 | * is fullfilled.
48 | * @param {?(function(this:THIS, *): *)=} opt_onRejected A function that will
49 | * be invoked with the rejection reason if the Promise is rejected.
50 | * @param {THIS=} opt_context An optional context object that will be the
51 | * execution context for the callbacks. By default, functions are executed
52 | * with the default this.
53 | * @return {!goog.Promise<RESULT>} A new Promise that will receive the result
54 | * of the fulfillment or rejection callback.
55 | * @template RESULT,THIS
56 | */
57 | goog.Thenable.prototype.then = function(opt_onFulfilled, opt_onRejected,
58 | opt_context) {};
59 |
60 |
61 | /**
62 | * An expando property to indicate that an object implements
63 | * {@code goog.Thenable}.
64 | *
65 | * {@see addImplementation}.
66 | *
67 | * @const
68 | */
69 | goog.Thenable.IMPLEMENTED_BY_PROP = '$goog_Thenable';
70 |
71 |
72 | /**
73 | * Marks a given class (constructor) as an implementation of Thenable, so
74 | * that we can query that fact at runtime. The class must have already
75 | * implemented the interface.
76 | * Exports a 'then' method on the constructor prototype, so that the objects
77 | * also implement the extern {@see goog.Thenable} interface for interop with
78 | * other Promise implementations.
79 | * @param {function(new:goog.Thenable,...[?])} ctor The class constructor. The
80 | * corresponding class must have already implemented the interface.
81 | */
82 | goog.Thenable.addImplementation = function(ctor) {
83 | goog.exportProperty(ctor.prototype, 'then', ctor.prototype.then);
84 | if (COMPILED) {
85 | ctor.prototype[goog.Thenable.IMPLEMENTED_BY_PROP] = true;
86 | } else {
87 | // Avoids dictionary access in uncompiled mode.
88 | ctor.prototype.$goog_Thenable = true;
89 | }
90 | };
91 |
92 |
93 | /**
94 | * @param {*} object
95 | * @return {boolean} Whether a given instance implements {@code goog.Thenable}.
96 | * The class/superclass of the instance must call {@code addImplementation}.
97 | */
98 | goog.Thenable.isImplementedBy = function(object) {
99 | if (!object) {
100 | return false;
101 | }
102 | try {
103 | if (COMPILED) {
104 | return !!object[goog.Thenable.IMPLEMENTED_BY_PROP];
105 | }
106 | return !!object.$goog_Thenable;
107 | } catch (e) {
108 | // Property access seems to be forbidden.
109 | return false;
110 | }
111 | };