github.com/secoba/wails/v2@v2.6.4/internal/frontend/runtime/desktop/calls.js (about)

     1  /*
     2   _       __      _ __
     3  | |     / /___ _(_) /____
     4  | | /| / / __ `/ / / ___/
     5  | |/ |/ / /_/ / / (__  )
     6  |__/|__/\__,_/_/_/____/
     7  The electron alternative for Go
     8  (c) Lea Anthony 2019-present
     9  */
    10  /* jshint esversion: 6 */
    11  
    12  export const callbacks = {};
    13  
    14  /**
    15   * Returns a number from the native browser random function
    16   *
    17   * @returns number
    18   */
    19  function cryptoRandom() {
    20  	var array = new Uint32Array(1);
    21  	return window.crypto.getRandomValues(array)[0];
    22  }
    23  
    24  /**
    25   * Returns a number using da old-skool Math.Random
    26   * I likes to call it LOLRandom
    27   *
    28   * @returns number
    29   */
    30  function basicRandom() {
    31  	return Math.random() * 9007199254740991;
    32  }
    33  
    34  // Pick a random number function based on browser capability
    35  var randomFunc;
    36  if (window.crypto) {
    37  	randomFunc = cryptoRandom;
    38  } else {
    39  	randomFunc = basicRandom;
    40  }
    41  
    42  
    43  /**
    44   * Call sends a message to the backend to call the binding with the
    45   * given data. A promise is returned and will be completed when the
    46   * backend responds. This will be resolved when the call was successful
    47   * or rejected if an error is passed back.
    48   * There is a timeout mechanism. If the call doesn't respond in the given
    49   * time (in milliseconds) then the promise is rejected.
    50   *
    51   * @export
    52   * @param {string} name
    53   * @param {any=} args
    54   * @param {number=} timeout
    55   * @returns
    56   */
    57  export function Call(name, args, timeout) {
    58  
    59  	// Timeout infinite by default
    60  	if (timeout == null) {
    61  		timeout = 0;
    62  	}
    63  
    64  	// Create a promise
    65  	return new Promise(function (resolve, reject) {
    66  
    67  		// Create a unique callbackID
    68  		var callbackID;
    69  		do {
    70  			callbackID = name + '-' + randomFunc();
    71  		} while (callbacks[callbackID]);
    72  
    73  		var timeoutHandle;
    74  		// Set timeout
    75  		if (timeout > 0) {
    76  			timeoutHandle = setTimeout(function () {
    77  				reject(Error('Call to ' + name + ' timed out. Request ID: ' + callbackID));
    78  			}, timeout);
    79  		}
    80  
    81  		// Store callback
    82  		callbacks[callbackID] = {
    83  			timeoutHandle: timeoutHandle,
    84  			reject: reject,
    85  			resolve: resolve
    86  		};
    87  
    88  		try {
    89  			const payload = {
    90  				name,
    91  				args,
    92  				callbackID,
    93  			};
    94  
    95              // Make the call
    96              window.WailsInvoke('C' + JSON.stringify(payload));
    97          } catch (e) {
    98              // eslint-disable-next-line
    99              console.error(e);
   100          }
   101      });
   102  }
   103  
   104  window.ObfuscatedCall = (id, args, timeout) => {
   105  
   106      // Timeout infinite by default
   107      if (timeout == null) {
   108          timeout = 0;
   109      }
   110  
   111      // Create a promise
   112      return new Promise(function (resolve, reject) {
   113  
   114          // Create a unique callbackID
   115          var callbackID;
   116          do {
   117              callbackID = id + '-' + randomFunc();
   118          } while (callbacks[callbackID]);
   119  
   120          var timeoutHandle;
   121          // Set timeout
   122          if (timeout > 0) {
   123              timeoutHandle = setTimeout(function () {
   124                  reject(Error('Call to method ' + id + ' timed out. Request ID: ' + callbackID));
   125              }, timeout);
   126          }
   127  
   128          // Store callback
   129          callbacks[callbackID] = {
   130              timeoutHandle: timeoutHandle,
   131              reject: reject,
   132              resolve: resolve
   133          };
   134  
   135          try {
   136              const payload = {
   137  				id,
   138  				args,
   139  				callbackID,
   140  			};
   141  
   142              // Make the call
   143              window.WailsInvoke('c' + JSON.stringify(payload));
   144          } catch (e) {
   145              // eslint-disable-next-line
   146              console.error(e);
   147          }
   148      });
   149  };
   150  
   151  
   152  /**
   153   * Called by the backend to return data to a previously called
   154   * binding invocation
   155   *
   156   * @export
   157   * @param {string} incomingMessage
   158   */
   159  export function Callback(incomingMessage) {
   160  	// Parse the message
   161  	let message;
   162  	try {
   163  		message = JSON.parse(incomingMessage);
   164  	} catch (e) {
   165  		const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`;
   166  		runtime.LogDebug(error);
   167  		throw new Error(error);
   168  	}
   169  	let callbackID = message.callbackid;
   170  	let callbackData = callbacks[callbackID];
   171  	if (!callbackData) {
   172  		const error = `Callback '${callbackID}' not registered!!!`;
   173  		console.error(error); // eslint-disable-line
   174  		throw new Error(error);
   175  	}
   176  	clearTimeout(callbackData.timeoutHandle);
   177  
   178  	delete callbacks[callbackID];
   179  
   180  	if (message.error) {
   181  		callbackData.reject(message.error);
   182  	} else {
   183  		callbackData.resolve(message.result);
   184  	}
   185  }