• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
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
16/**
17 * Intercept callback from native and forward to user-defined callback.
18 * @param {*} args - Args.
19 * @param {boolean} [needPromise] - If asynchronous operations are needed.
20 * @return {Object} If promise are needed, return { args, promise }. Otherwise return args.
21 */
22export function interceptCallback(args: any, needPromise?: boolean): object {
23  if (args.length === 0 && !needPromise) {
24    return args;
25  }
26  const first: object = args[0];
27  const callbacks: object = {};
28  let hasProperty: boolean = false;
29  if (typeof first === 'object' &&
30    Object.prototype.toString.call(first).toLowerCase() === '[object object]' &&
31    args.length === 1
32  ) {
33    for (const key in first) {
34      const value: Function = first[key];
35      if (typeof value === 'function') {
36        callbacks[key] = value;
37      } else {
38        hasProperty = true;
39      }
40    }
41  } else {
42    hasProperty = true;
43  }
44
45  let promise: any;
46  const callbLength: number = Object.keys(callbacks).length;
47  if (needPromise) {
48    if (callbLength <= 0) {
49      promise = new PromiseRef();
50    }
51  }
52  if (callbLength > 0 || promise) {
53    const callb = (msg: { method: string; arguments: any; }) => {
54      let func = callbacks[msg.method];
55      const callbArgs: any = msg.arguments;
56
57      if (func !== undefined) {
58        func(...callbArgs);
59      }
60
61      // Always call complete().
62      func = callbacks['complete'];
63      if (func !== undefined) {
64        func(...callbArgs);
65      }
66      if (promise) {
67        const data: any = callbArgs &&
68          callbArgs.length > 0
69          ? callbArgs[0]
70          : undefined;
71        if ('success' === msg.method || 'callback' === msg.method) {
72          promise.resolve({ data });
73        } else {
74          // 200 means common error ,100 :cancel.
75          const code: any =
76            'cancel' === msg.method
77              ? 100
78              : callbArgs && callbArgs.length > 1
79                ? callbArgs[1]
80                : 200;
81          promise.reject({ data, code });
82        }
83      }
84    };
85    callb.__onlyPromise = callbLength <= 0;
86
87    if (hasProperty) {
88      args.push(callb);
89    } else {
90      args = [callb];
91    }
92  }
93  return needPromise ? { args, promise } : args;
94}
95
96/**
97 * This class provide a Promise object for asynchronous operation processing.
98 */
99class PromiseRef {
100  private _promise: Promise<object>;
101  private _reject: Function;
102  private _resolve: Function;
103
104  constructor() {
105    this._promise = new Promise((resolve, reject) => {
106      this._reject = reject;
107      this._resolve = resolve;
108    });
109  }
110
111  /**
112   * Promise of this PromiseRef.
113   * @type {Promise}
114   */
115  public get promise() {
116    return this._promise;
117  }
118
119  public set promise(newPromise) {
120    this._promise = newPromise;
121  }
122
123  /**
124   * Reject function using the Promise object.
125   * @type {Promise}
126   */
127  public get reject() {
128    return this._reject;
129  }
130
131  public set reject(data) {
132    this._reject = data;
133  }
134
135  /**
136   * Resolve function using the Promise object.
137   * @type {Promise}
138   */
139  public get resolve() {
140    return this._resolve;
141  }
142
143  public set resolve(data) {
144    this._resolve = data;
145  }
146}
147