Прокси для ленивых обещаний

JavaScript

задний план

Как мы все знаем, es6 принес нам нового босса в мире мета-операций — Прокси.

Преимущества по сравнению с Object.defineProperty:

  • небольшая начальная сумма
  • доступный массив
  • Добавление и удаление полей является конфиденциальным
  • Множественный перехват

Для студентов, которые мало знают о прокси, вы можете обратиться по следующей ссылке.

Proxy-MDN

Начало работы с прокси-ECMAScript 6

Ленивые обещания

Давайте найдем каштаны, чтобы выполнить это ленивое обещание.

В экосистеме WeChat сегодня многие до сих пор молча используют коллбэки, если управление нехорошее, то легко попасть в ад колбэков, а использовать настоящую асинхронность невозможно.

Хотя сейчас есть много решений для его реализации, давайте на этот раз забудем об этом и реализуем по-своему.

Наша главная цель — одеть эту ручку без макияжа как модное обещание.

wx.showToast({
  title: '成功',
  success () {
  	console.log('success')
  },
  fail () {
  	console.log('fail')
  }
})
// 这里把wx的api代理到wxq变量
wxq.showToast({title: '成功'})
  .then(() => console.log('success'))
  .catch(() => console.log('fail'))
  .finally(() => console.log('finally'))

единственное обещание

Основное - напрямую инкапсулировать функцию, а потом вкладывать в нее апи каждый раз при использовании, но при использовании нет эстетического ощущения, деформируется операция, и есть лишний слой оболочки

function wxPromise(fn, param){
  return new Promise((resolve, reject) => {
    const data = Object.assign({
      success(res) {
        resolve(res)
      },
      fail(res){
        reject(res)
      }
    }, param)
    fn(data);
  })
}
wxPromise(wxq.showToast, {title: '成功'})
  .then(() => console.log('success'))
  .catch(() => console.log('fail'))
  .finally(() => console.log('finally'))

Прокси-метод

Прежде чем писать, давайте предположим, что если мы столкнемся с подобным сценарием в следующий раз. Переходя на uni-app или другой подобный фреймворк, можем ли мы продолжать повторно использовать часть кода? Как должен быть разработан этот код?

Поэтому я решил разделить код на 3 части.

  • Функция генерации прокси: прокси в соответствии с функцией шаблона обещания
  • Функция шаблона обещания: дополнение в зависимости от среды
  • Функция выхода: скрыть некоторые сгенерированные подробные операции
// proxy生成函数
function createProxyAll (obj, fn) {
  return new Proxy(obj, {
    get(target, key, receiver) {
      // 操作receiver会循环
      if (!target[key]) target[key] = fn(key)
      return Reflect.get(target, key, receiver);
    }
  })
}
// promise模板函数
function wxPromise(key){
  // 缓存留key生成一个promise闭包
  return function (param) {
    return new Promise((resolve, reject) => {
      const data = Object.assign({
        success(res) {
          resolve(res)
        },
        fail(res){
          reject(res)
        }
      }, param)
      wx[key](data);
    })
  }
}
// 出口函数
function wxPromiseAll () {
  return createProxyAll(wx, wxPromise)
}

изящная деградация

Хорошие вещи более или менее не понимаются миром. Я использовал это решение перед тем, как спуститься.В солнечный день оператор поспешил сказать мне, что мобильный телефон клиента был полностью пуст, и я немного вспотел при 26°C.

в то время как (правда) {думая}.png

Выяснилось, что это проблема совместимости с прокси.

  • Все просто, пусть клиент меняет телефон (отказал).
  • Шимовая библиотека? Мета-операции, такие как proxy и Object.defineProperty, не могут быть прокладками.Если среда не поддерживает их, они не поддерживаются. Это прямая причина, по которой vue2 и vue3 не могут обеспечить совместимость с браузерами более ранних версий (×)
  • Понизить версию с помощью defineProperty√
function make (obj, fn) {
  // 判断Proxy,是否需要降级
  if (typeof Proxy === 'function') {
    return createProxyAll(obj, fn)
  } else {
    return createdefinePropertyAll(obj, fn)
  }
}
function createdefinePropertyAll (obj, fn) {
  const _obj = {}
  const result = {}
  Object.keys(obj).forEach(key => {
    Object.defineProperty(result, key, {
      get() {
      	// 这里的判断和proxy一样,防止引用循环
        if (!_obj[key]) _obj[key] = fn(key)
        return _obj[key]
      },
    })
  })
  return result
}

Реализация версии defineProperty аналогична, и видно, что все поля напрямую проксируются при инициализации версии defineProperty, поэтому производительность vue3, реализованной через proxy, лучше, чем производительность vue2, реализованной с помощью defineProperty. Точно так же, почему я говорю, что это ленивый промис, только когда вы его используете, операция перехвата будет изменена на промис без инициализации всего сразу

конец пьесы

Код можно посмотреть здесь

Я думаю, возьми трубку, увидишь твой комментарий, чем богиня Хаоши