工作手记 2021/10/13

252 阅读2分钟

这两天遇到一个需求,修改一个组件里的变量(A)。其他的组件里的数据需要根据这个变量去请求一个接口,并等这个接口返回数据后对组件里的数据进行处理。

正常的处理方法是:

先等变量(A)变化后去请求数据,等数据处理返回后把数据存到一个全局变量再去触发其他组件的变化。

这样就有个问题,这个全局变量是被动触发的,再某些特性场景下去取值,如果没有。要立即调用接口并等待返回后再进行下一步处理。这样代码处理的起立就要处理几个步骤,要先判断有没有,没有要调用接口并等待

这样我就想了一个新的办法通过 闭包 + promise + proxy 写了一个方法。对已经请求过的值进行保存,没有的值就行请求,如果这个值再请求的过程中,就等待这个请求完成后返回,这样就既能减少对服务器的请求压力,又能减少等待时间。举个例子,如果已经有一个请求需要10S,当进行了5S后再次调用这个方法,只需要再等5S就可以拿到返回的结果

代码如下:

这个方法的缺点是多次调用的入参耦合度要求高,否则也会多次调用接口请求

function findData() {
  let data = {};
  return function getData(key) {
    return new Promise((resolve) => {
      if (!data[key] && data[key] !== null) {
        data[key] = null; // 先给个默认值NULL ,让后面的调用知道已经再发起请求了

        // this.$http
        //   .post(utl, params)
        //   .then((res) => {
        //     data[key] = res;
        //     resolve(data[key]);
        //   })
        //   .catch((e) => {
        // 如果请求失败一定要把data[key] 删除,否则就永远拿不到值,也不会再发起请求
        //     delete data[key];
        //     resolve(null);
        //   });

        //用 setTimeout 模拟异步请求
        setTimeout(() => {
          data[key] = 1;
          resolve(data[key]);
        }, 1000);
      } else if (data[key] === null) {
        data = new Proxy(data, {
          set: function (target, name, value, receiver) {
            if (name === key) {
              //当DATA里的KEY值有变化说明已经请求完成,并修改值
              resolve(value);
            }
            return Reflect.set(target, name, value, receiver);
          },
        });
      } else {
        resolve(data[key]);
      }
    });
  };
}

// 使用方法

let getData = findData();
let A = 'key'; // 变量A
// 再不同的地方 被动触发,(变量A变化后,去触发)
getData(A).then((res) => {
  console.log('发请求', res);
}); // 发起请求 返回1

getData(A).then((res) => {
  console.log('不等待,不发请求', res);
}); // 不发起请求 同时返回1
setTimeout(() => {
  getData(A).then((res) => {
    console.log('等待0.5S', res);
  }); // 不发起请求 同时返回1
}, 500);



// 也可以
(async () => {
  const data = await getData(A);
  console.log('data', data); // data = 1
})();

// 这个方法的缺点是多次调用的入参耦合度要求高,否则也会多次调用接口请求