API Promisify 化得不够好,浪费性能,不够灵活。所以我自己实现了一个。
发布于 5 年前 作者 xuexiuying 1406 次浏览 来自 分享

API Promisify 化得不够好,浪费性能,不够灵活。所以我自己实现了一个。用9结尾来表示异步,Storage操作我另封装有方法,所以跳过。

///// var.js

/**
 *
 * [@param](/user/param) r
 */
let async2resolve = function (r) {
  let {_resolve_} = this;
  if (_resolve_) {
    _resolve_(r);
    async2destructor(this);
  } else {
    this.returns = {
      res: r
    }
  }
};
/**
 *
 * [@param](/user/param) r
 */
let async2reject = function (r) {
  let {_reject_} = this;
  if (_reject_) {
    _reject_(r);
    async2destructor(this);
  } else {
    this.returns = {
      rej: r
    }
  }
};
let async2destructor = function (async2) {
  return removeProperty(async2)
};
/**
 *
 * [@returns](/user/returns) {{resolve: async2resolve, reject: async2reject,promise:Promise}}
 */
va.createAsync2 = function () {
  /**
   *
   * [@type](/user/type) {{resolve: async2resolve, reject: async2reject,promise?:Promise,_resolve_?,_reject_?,returns?}}
   */
  let async2 = {resolve: async2resolve, reject: async2reject};
  async2.promise = new Promise(function (resolve, reject) {
    let {returns} = async2;
    if (returns) {
      if (returns.res) {
        resolve(returns.res);
      } else {
        reject(returns.rej);
      }
      async2destructor(async2);
    } else {
      async2._resolve_ = resolve;
      async2._reject_ = reject;
    }
  });
  return async2;
};
/////  apiProcess.js
const {createAsync2, isObject, isFunction, assign, noop} = global.va;
const setSuccessFailNull = function (params) {
  if (params) {
    params.success = params.fail = null;
  }
};
const setSuccessFail = function (params, resolve, reject) {
  if (params) {
    params.success = resolve;
    params.fail = reject;
  }
};
const createMaxQueue = (max) => {
  let queue = [];
  queue.max = max;
  queue.count = 0;
};

const execMaxQueueCall = function (queue) {
  if (queue && !(queue.max < queue.count)) {
    if (queue && queue.length > 0) {
      let fn = queue.shift();
      queue.count = Math.max(0, queue.count - 1 || 0);
      if (fn) {
        fn();
      } else {
        execMaxQueueCall(queue)
      }
    }
  }
};
const completePromise = function (res, reF, queue) {
  execMaxQueueCall(queue);
  reF(res);
};
const queueAdd = function (queue, func) {
  if (queue) {
    queue.push(func);
    queue.count = queue.count + 1 || 1;
    execMaxQueueCall(queue)
  } else {
    func();
  }
};
const processParams = function (fn, params, resolve, reject, queue) {
  let success, fail;
  if (queue) {
    success = function (res) {
      completePromise(res, resolve, queue);
    };
    fail = function (res) {
      completePromise(res, reject, queue);
    };
  } else {
    success = resolve;
    fail = reject;
  }
  setSuccessFail(params, success, fail);
};
const setReturns = function (promise, returns_name, returns) {
  return promise.setReturns(returns_name || 'returns', returns)
};
const createAsync2Call = function (asyncFn, params, async2) {
  return function () {
    let ret = asyncFn(params);
    setSuccessFailNull(params);
    async2.resolve(ret);
    async2 = params = null;
  }
};
const createCall = function (asyncFn, params) {
  return function () {
    asyncFn(params);
    setSuccessFailNull(params);
    params = null;
  }
};
const taskFn = {
  abort: function () {
    this.call('abort')
  },
  on: function (Name, handle) {
    this.call(`on${Name}`, handle)
  },
  off: function (Name, handle) {
    this.call(`off${Name}`, handle)
  }
};
const noopTaskFn = {
  abort: noop,
  on: noop,
  off: noop
};
const promisify = function (name, asyncFn, has_returns, returns_name, max) {
  let has_max = !!max;
  let fn9 = has_returns ? function fn(params) {
    let async2 = createAsync2(), {promise} = async2, is_task = returns_name === 'task', noop_task = is_task && params.noopTask;
    return setReturns(new Promise((resolve, reject) => {
      let queue = has_max && fn.maxQueue;
      processParams(params, resolve, reject, queue);
      queueAdd(queue, createAsync2Call(asyncFn, params, async2));
      async2 = params = null;
    }), returns_name, is_task ? assign(promise, noop_task ? noopTaskFn : taskFn) : promise);
  } : function fn(params) {
    return new Promise((resolve, reject) => {
      let queue = has_max && fn.maxQueue;
      processParams(params, resolve, reject, queue);
      queueAdd(queue, createCall(asyncFn, params));
      params = null;
    })
  };
  if (has_max) {
    fn9.maxQueue = createMaxQueue(max);
  }
  return fn9;
};

/**
 *
 * [@param](/user/param) {Wx9|WxCloud|Object} api
 * [@param](/user/param) returnsNameMap
 * [@param](/user/param) extraFn
 * [@returns](/user/returns) {Wx9}
 */
let initApiPromisify = (api, returnsNameMap, extraFn) => {
  let ed = '_initializedApiPromisify';
  returnsNameMap = returnsNameMap || {};
  if (api[ed]) {
    return api;
  }
  api[ed]=true;
  let noopR = /^on|^off|^create|Manager$|Sync$|Storage|9$|^canI|arrayBuffer|^getMenu|^report|nextTick/i, requestR = /^request|^(up|down)load/, connectR = /^connect/;
  for (let name in api) {
    let fn;
    if (api.hasOwnProperty(name) && !noopR.test(name) && isFunction(fn = api[name])) {
      let is_request = requestR.test(name), is_connect = !is_request && connectR.test(name), has_returns, is_task = has_returns = is_request || is_connect;
      api[name + '9'] = promisify(name, fn,
        has_returns, returnsNameMap[name] || (is_task && 'task'),
        is_request ? 10 : is_connect ? 5 : false);
    }
  }
  if (extraFn) {
    api.promisify = promisify;
    api.taskFn = taskFn;
    api.noopTaskFn = noopTaskFn;
    if (isObject(extraFn)) {
      assign(api, extraFn);
    }
  }
  return api;
};
module.exports = {
  taskFn: taskFn,
  noopTaskFn: noopTaskFn,
  promisify,
  initApiPromisify
};

////LocalStorage.js
const {va:{sre, isObject, isArray, eachIn, getPropByPath, isNumber, isString, isFunction},Fns}=global;
let storage;
storage = {
  isExpired: (data, expire_prop_name_path) => {
    return data
      && (data = +getPropByPath(
        data, isString(expire_prop_name_path)
        || isNumber(expire_prop_name_path)
        || isArray(expire_prop_name_path)
          ? expire_prop_name_path : ['expires']))
      && data <= Date.now()
  },
  has: (key) => {
    let info = storage.info();
    return (info && info.keys || []).indexOf(key) > -1
  },
  get: (key, ret_sre) => {
    let ret;
    try {
      if (storage.has(key)) {
        ret = Fns.getStorageSync(key);
      }
      return ret_sre ? sre(true, ret) : ret;
    } catch (e) {
      return ret_sre ? sre(false, e) : ret;
    }
  },
  get9: (key) => Fns.getStorage({key}),
  map: (keys, ret_sre) => keys.map((key) => storage.get(key, ret_sre)),
  map9: (keys, ret_sre) => Promise.all(keys.map((key) => storage.get9(key, ret_sre))),
  set: function (key, data) {
    try {
      let state = true, setStorageSync = Fns.setStorageSync;
      if (!arguments.length && isObject(key)) {
        eachIn(key, (data, key) => {
          try {
            setStorageSync(key, data);
          } catch (e) {
            state = false
          }
        })
      } else {
        setStorageSync(key, data);
      }
      return state
    } catch (e) {
      return false
    }
  },
  set9: function (key, data) {
    let setStorage = Fns.setStorage;
    if (!arguments.length && isObject(key)) {
      let map = [];
      eachIn(key, (data, key) => {
        map.push(setStorage({key, data}));
      });
      return Promise.all(map)
    }
    return setStorage({key, data});
  },
  info: () => {
    try {
      return Fns.getStorageInfoSync()
    } catch (e) {
    }
  },
  info9: () => Fns.getStorageInfo(),
  remove: (key) => {
    try {
      let removeStorageSync = Fns.removeStorageSync;
      let state = true;
      if (isArray(key)) {
        key.forEach((key) => {
          try {
            removeStorageSync(key)
          } catch (e) {
            state = false;
          }
        })
      } else {
        removeStorageSync(key);
      }
      return state
    } catch (e) {
      return false
    }
  },
  remove9: (key) => {
    let removeStorage = Fns.removeStorage;
    return isArray(key) ? Promise.all(key.map((key) => {
      return removeStorage({key})
    })) : removeStorage({key})
  },
  clear: (exclusions) => {
    try {
      exclusions = isString(exclusions) ? [exclusions] : exclusions;
      if (exclusions && exclusions.length) {
        let info = storage.info();
        return storage.remove(info && info.keys.excludeByValues(exclusions).reserved)
      }
      Fns.clearStorageSync();
      return true;
    } catch (e) {
      return false
    }
  },
  clear9: (exclusions) => {
    let reserved, ex;
    if (isFunction(exclusions)) {
      reserved = exclusions(storage);
      ex = true;
    } else if (exclusions) {
      exclusions = isString(exclusions) ? [exclusions] : exclusions;
      if (exclusions.length) {
        let info = storage.info();
        reserved = info && info.keys.excludeByValues(exclusions).reserved;
        ex = true;
      }
    }
    if (ex) {
      return storage.remove9(reserved)
    }
    Fns.clearStorageSync();
    return Fns.clearStorage();
  },
  extract: (keys, ret_sre) => {
    let part = {};
    keys.forEach((key) => {
      part[key] = storage.get(key, ret_sre);
    });
    return part;
  },
  extract9: (keys) => {
    let part = {};
    keys.forEach((key) => {
      part[key] = storage.get9(key);
    });
    return part;
  }
};
module.exports = storage;

////wx9.d.ts
/// 
import WP = WechatMiniprogram;
type taskFn = {
  abort(),
  on(Name, handle),
  off(Name, handle)
};
interface Wx9 extends WP.Wx
{
  canvasToTempFilePath9(options?:WP.CanvasToTempFilePathOption):Promise;
  canvasGetImageData9(options?:WP.CanvasGetImageDataOption):Promise;
  canvasPutImageData9(options?:WP.CanvasPutImageDataOption):Promise;
  getShareInfo9(options?:WP.GetShareInfoOption):Promise;
  pageScrollTo9(options?:WP.PageScrollToOption):Promise;
  chooseInvoiceTitle9(options?:WP.ChooseInvoiceTitleOption):Promise;
  chooseInvoice9(options?:WP.ChooseInvoiceOption):Promise;
  openSetting9(options?:WP.OpenSettingOption):Promise;
  getExtConfig9(options?:WP.GetExtConfigOption):Promise;
  chooseMedia9(options?:WP.ChooseMediaOption):Promise;
  chooseMessageFile9(options?:WP.ChooseMessageFileOption):Promise;
  showShareMenu9(options?:WP.ShowShareMenuOption):Promise;
  hideShareMenu9(options?:WP.HideShareMenuOption):Promise;
  updateShareMenu9(options?:WP.UpdateShareMenuOption):Promise;
  setNavigationBarColor9(options?:WP.SetNavigationBarColorOption):Promise;
  vibrateShort9(options?:WP.VibrateShortOption):Promise;
  vibrateLong9(options?:WP.VibrateLongOption):Promise;
  getSetting9(options?:WP.GetSettingOption):Promise;
  showRedPackage9(options?:WP.ShowRedPackageOption):Promise;
  addPhoneContact9(options?:WP.AddPhoneContactOption):Promise;
  setScreenBrightness9(options?:WP.SetScreenBrightnessOption):Promise;
  getScreenBrightness9(options?:WP.GetScreenBrightnessOption):Promise;
  getWeRunData9(options?:WP.GetWeRunDataOption):Promise;
  navigateToMiniProgram9(options?:WP.NavigateToMiniProgramOption):Promise;
  navigateBackMiniProgram9(options?:WP.NavigateBackMiniProgramOption):Promise;
  setTopBarText9(options?:WP.SetTopBarTextOption):Promise;
  setTabBarBadge9(options?:WP.SetTabBarBadgeOption):Promise;
  removeTabBarBadge9(options?:WP.RemoveTabBarBadgeOption):Promise;
  showTabBarRedDot9(options?:WP.ShowTabBarRedDotOption):Promise;
  hideTabBarRedDot9(options?:WP.HideTabBarRedDotOption):Promise;
  showTabBar9(options?:WP.ShowTabBarOption):Promise;
  hideTabBar9(options?:WP.HideTabBarOption):Promise;
  setTabBarStyle9(options?:WP.SetTabBarStyleOption):Promise;
  setTabBarItem9(options?:WP.SetTabBarItemOption):Promise;
  setBackgroundColor9(options?:WP.SetBackgroundColorOption):Promise;
  setBackgroundTextStyle9(options?:WP.SetBackgroundTextStyleOption):Promise;
  setEnableDebug9(options?:WP.SetEnableDebugOption):Promise;
  setKeepScreenOn9(options?:WP.SetKeepScreenOnOption):Promise;
  checkIsSupportSoterAuthentication9(options?:WP.CheckIsSupportSoterAuthenticationOption):Promise;
  startSoterAuthentication9(options?:WP.StartSoterAuthenticationOption):Promise;
  checkIsSoterEnrolledInDevice9(options?:WP.CheckIsSoterEnrolledInDeviceOption):Promise;
  setNavigationBarTitle9(options?:WP.SetNavigationBarTitleOption):Promise;
  showNavigationBarLoading9(options?:WP.ShowNavigationBarLoadingOption):Promise;
  hideNavigationBarLoading9(options?:WP.HideNavigationBarLoadingOption):Promise;
  hideHomeButton9(options?:WP.HideHomeButtonOption):Promise;
  startPullDownRefresh9(options?:WP.StartPullDownRefreshOption):Promise;
  stopPullDownRefresh9(options?:WP.StopPullDownRefreshOption):Promise;
  getSelectedTextRange9(options?:WP.GetSelectedTextRangeOption):Promise;
  openBluetoothAdapter9(options?:WP.OpenBluetoothAdapterOption):Promise;
  closeBluetoothAdapter9(options?:WP.CloseBluetoothAdapterOption):Promise;
  getBluetoothAdapterState9(options?:WP.GetBluetoothAdapterStateOption):Promise;
  startBluetoothDevicesDiscovery9(options?:WP.StartBluetoothDevicesDiscoveryOption):Promise;
  stopBluetoothDevicesDiscovery9(options?:WP.StopBluetoothDevicesDiscoveryOption):Promise;
  getBluetoothDevices9(options?:WP.GetBluetoothDevicesOption):Promise;
  getConnectedBluetoothDevices9(options?:WP.GetConnectedBluetoothDevicesOption):Promise;
  closeBLEConnection9(options?:WP.CloseBLEConnectionOption):Promise;
  getBLEDeviceServices9(options?:WP.GetBLEDeviceServicesOption):Promise;
  getBLEDeviceCharacteristics9(options?:WP.GetBLEDeviceCharacteristicsOption):Promise;
  notifyBLECharacteristicValueChange9(options?:WP.NotifyBLECharacteristicValueChangeOption):Promise;
  readBLECharacteristicValue9(options?:WP.ReadBLECharacteristicValueOption):Promise;
  writeBLECharacteristicValue9(options?:WP.WriteBLECharacteristicValueOption):Promise;
  startBeaconDiscovery9(options?:WP.StartBeaconDiscoveryOption):Promise;
  stopBeaconDiscovery9(options?:WP.StopBeaconDiscoveryOption):Promise;
  getBeacons9(options?:WP.GetBeaconsOption):Promise;
  startWifi9(options?:WP.StartWifiOption):Promise;
  stopWifi9(options?:WP.StopWifiOption):Promise;
  getWifiList9(options?:WP.GetWifiListOption):Promise;
  getConnectedWifi9(options?:WP.GetConnectedWifiOption):Promise;
  connectWifi9(options?:WP.ConnectWifiOption):Promise;
  setWifiList9(options?:WP.SetWifiListOption):Promise;
  getHCEState9(options?:WP.GetHCEStateOption):Promise;
  startHCE9(options?:WP.StartHCEOption):Promise;
  stopHCE9(options?:WP.StopHCEOption):Promise;
  sendHCEMessage9(options?:WP.SendHCEMessageOption):Promise;
  startLocalServiceDiscovery9(options?:WP.StartLocalServiceDiscoveryOption):Promise;
  stopLocalServiceDiscovery9(options?:WP.StopLocalServiceDiscoveryOption):Promise;
  redirectTo9(options?:WP.RedirectToOption):Promise;
  reLaunch9(options?:WP.ReLaunchOption):Promise;
  navigateTo9(options?:WP.NavigateToOption):Promise;
  switchTab9(options?:WP.SwitchTabOption):Promise;
  navigateBack9(options?:WP.NavigateBackOption):Promise;
  getBackgroundFetchData9(options?:WP.GetBackgroundFetchDataOption):Promise;
  setBackgroundFetchToken9(options?:WP.SetBackgroundFetchTokenOption):Promise;
  getBackgroundFetchToken9(options?:WP.GetBackgroundFetchTokenOption):Promise;
  request9(options?:WP.RequestOption):Promise;
  connectSocket9(options?:WP.ConnectSocketOption):Promise;
  closeSocket9(options?:WP.CloseSocketOption):Promise;
  sendSocketMessage9(options?:WP.SendSocketMessageOption):Promise;
  uploadFile9(options?:WP.UploadFileOption):Promise;
  downloadFile9(options?:WP.DownloadFileOption):Promise;
  chooseImage9(options?:WP.ChooseImageOption):Promise;
  previewImage9(options?:WP.PreviewImageOption):Promise;
  getImageInfo9(options?:WP.GetImageInfoOption):Promise;
  saveImageToPhotosAlbum9(options?:WP.SaveImageToPhotosAlbumOption):Promise;
  compressImage9(options?:WP.CompressImageOption):Promise;
  startRecord9(options?:any):Promise;
  stopRecord9(options?:any):Promise;
  playVoice9(options?:WP.PlayVoiceOption):Promise;
  pauseVoice9(options?:WP.PauseVoiceOption):Promise;
  stopVoice9(options?:WP.StopVoiceOption):Promise;
  chooseVideo9(options?:WP.ChooseVideoOption):Promise;
  saveVideoToPhotosAlbum9(options?:WP.SaveVideoToPhotosAlbumOption):Promise;
  loadFontFace9(options?:WP.LoadFontFaceOption):Promise;
  getLocation9(options?:WP.GetLocationOption):Promise;
  openLocation9(options?:WP.OpenLocationOption):Promise;
  chooseLocation9(options?:WP.ChooseLocationOption):Promise;
  startLocationUpdateBackground9(options?:WP.StartLocationUpdateBackgroundOption):Promise;
  startLocationUpdate9(options?:WP.StartLocationUpdateOption):Promise;
  stopLocationUpdate9(options?:WP.StopLocationUpdateOption):Promise;
  getNetworkType9(options?:WP.GetNetworkTypeOption):Promise;
  getSystemInfo9(options?:WP.GetSystemInfoOption):Promise;
  getBatteryInfo9(options?:WP.GetBatteryInfoOption):Promise;
  startAccelerometer9(options?:WP.StartAccelerometerOption):Promise;
  stopAccelerometer9(options?:WP.StopAccelerometerOption):Promise;
  startCompass9(options?:WP.StartCompassOption):Promise;
  stopCompass9(options?:WP.StopCompassOption):Promise;
  startDeviceMotionListening9(options?:WP.StartDeviceMotionListeningOption):Promise;
  stopDeviceMotionListening9(options?:WP.StopDeviceMotionListeningOption):Promise;
  startGyroscope9(options?:WP.StartGyroscopeOption):Promise;
  stopGyroscope9(options?:WP.StopGyroscopeOption):Promise;
  getBackgroundAudioPlayerState9(options?:WP.GetBackgroundAudioPlayerStateOption):Promise;
  playBackgroundAudio9(options?:WP.PlayBackgroundAudioOption):Promise;
  pauseBackgroundAudio9(options?:WP.PauseBackgroundAudioOption):Promise;
  seekBackgroundAudio9(options?:WP.SeekBackgroundAudioOption):Promise;
  stopBackgroundAudio9(options?:WP.StopBackgroundAudioOption):Promise;
  requestSubscribeMessage9(options?:WP.RequestSubscribeMessageOption):Promise;
  login9(options?:WP.LoginOption):Promise;
  checkSession9(options?:WP.CheckSessionOption):Promise;
  authorize9(options?:WP.AuthorizeOption):Promise;
  getUserInfo9(options?:WP.GetUserInfoOption):Promise;
  requestPayment9(options?:WP.RequestPaymentOption):Promise;
  addCard9(options?:WP.AddCardOption):Promise;
  openCard9(options?:WP.OpenCardOption):Promise;
  scanCode9(options?:WP.ScanCodeOption):Promise;
  chooseAddress9(options?:WP.ChooseAddressOption):Promise;
  saveFile9(options?:WP.FileSystemManagerSaveFileOption):Promise;
  openDocument9(options?:WP.OpenDocumentOption):Promise;
  getSavedFileList9(options?:WP.FileSystemManagerGetSavedFileListOption):Promise;
  getSavedFileInfo9(options?:WP.FileSystemManagerGetSavedFileInfoOption):Promise;
  getFileInfo9(options?:WP.FileSystemManagerGetFileInfoOption):Promise;
  removeSavedFile9(options?:WP.FileSystemManagerRemoveSavedFileOption):Promise;
  chooseContact9(options?:any):Promise;
  makePhoneCall9(options?:WP.MakePhoneCallOption):Promise;
  getAvailableAudioSources9(options?:WP.GetAvailableAudioSourcesOption):Promise;
  setInnerAudioOption9(options?:WP.SetInnerAudioOption):Promise;
  hideKeyboard9(options?:WP.HideKeyboardOption):Promise;
  showModal9(options?:WP.ShowModalOption):Promise;
  showToast9(options?:WP.ShowToastOption):Promise;
  hideToast9(options?:WP.HideToastOption):Promise;
  showLoading9(options?:WP.ShowLoadingOption):Promise;
  hideLoading9(options?:WP.HideLoadingOption):Promise;
  showActionSheet9(options?:WP.ShowActionSheetOption):Promise;
  getClipboardData9(options?:WP.GetClipboardDataOption):Promise;
  setClipboardData9(options?:WP.SetClipboardDataOption):Promise;
  promisify(fnName, asyncFn, hasReturns, returnsName, queueMax):any;
  taskFn:taskFn;
  noopTaskFn:taskFn;
}
declare const wx: Wx9;

1 回复

如果中华民族想实现如推背图所预言的天下大同,那么外国人永久居住条例就应该通过,更不应该歧视黑人,跪舔白人。

回到顶部