防抖(debounce)处理时,如何传回不同参数?

发布于 2022-09-12 04:27:33 字数 1145 浏览 35 评论 0

我有一个接口,传入id,传出value;
由于多处需要使用到这个接口,我就想到可以把这些id拼接后,进行请求再进行分发;

const set = new Set();
let timer;
function collect(idList) {
  return new Promise((resolve, reject) => {
    idList.forEach((id) => {
      set.add(id);
    });
    clearTimeout(timer);
    timer = setTimeout(async () => {
      const valueList = await getValue();
      resolve(
        valueList
          .filter((item) => idList.includes(item.id))
          .map((item) => item.value)
      );
    }, 300);
  });
}

// 模拟请求
function getValue() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(Array.from(set).map((id) => ({ id, value: id + '' })));
    }, 300);
  });
}

collect([1, 2, 3, 4]).then((list) => {
  console.log(list);
});
collect([1, 3, 5, 7]).then((list) => {
  console.log(list);
});
collect([9, 8, 7, 6]).then((list) => {
  console.log(list);
});

// 期望输出
// ['1', '2', '3', '4'] 
// ['1', '3', '5', '7']
// ['9', '8', '7', '6']

// 实际输出
// ['9', '8', '7', '6']

我是这么写的,但是这样的话 resolve 就被 clearTimeout 清除了。
这种情况下,应该怎么处理?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

海风掠过北极光 2022-09-19 04:27:33

这里我们需要 Deferred 对象来处理,就会简单很多。

简单分析,我们需要两步,第一步压入待发送请求,第二步合并参数使用一个请求发送。你需要的 debounce 效果就是,每次做第一步动作的时候都起一个定时器去做第二步。


// 我们需要把 Promise 对象转换成 Deferred 对象
// 因为需要在外部 resolve / reject promise
class Deferred {
  constructor() {
    this.promise = new Promise((res, rej) => {
      this.resolve = res;
      this.reject = rej;
    });
  }
}

class IdFetchTaskRunner {
  constructor() {
    this.tasks = [];
  }

  createTask(idList) {
    // 有一位乘客要上车
    const deferred = new Deferred();
    // 售票员车票存根,下车叫你要用
    this.tasks.push({ idList, deferred });
    // 返回给你的车票
    return deferred.promise;
  }

  async execute() {
    const tasks = this.tasks;
    // 发完车清空座位,下一波要用
    this.tasks = [];

    try {
      // 以下是本次发车过程
      const set = new Set(tasks.reduce((idList, task) => {
        return idList.concat(task.idList);
      }, []));

      const valueList = await getValue(set);
      // 转换成 map 处理
      const valueMap = valueList.reduce((m, item) => {
        m[item.id] = item.value;
        return m;
      }, {});
      // 遍历 tasks 依次 resolve ,(到站了,让每位乘客下车)
      tasks.forEach(task => {
        return task.deferred.resolve(task.idList.map(id => valueMap[id]));
      });
    } catch(e) {
      //(车抛锚了,让每位乘客下车)
      tasks.forEach(task => task.deferred.reject(e));
    }

  }
}

let taskRunner = new IdFetchTaskRunner();
let timer;
function collect(idList) {
  // 等等我,我也要上车
  clearTimeout(timer);
  // ok,重新算时间,300 ms 后发车,赶紧上
  timer = setTimeout(() => taskRunner.execute(), 300);
  // 这是你的车票拿好了
  return taskRunner.createTask(idList);
}

// 模拟请求,改为发送入参
function getValue(set) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(Array.from(set).map((id) => ({ id, value: id + '' })));
    }, 300);
  });
}

collect([1, 2, 3, 4]).then((list) => {
  console.log(list);
});
collect([1, 3, 5, 7]).then((list) => {
  console.log(list);
});

setTimeout(() => {
  // 同一拨
  collect([3, 8, 1, 6]).then((list) => {
    console.log(list);
  });
}, 100);

setTimeout(() => {
  // 这块赶不上了,只能下一波发车了
  collect([1, 1, 2, 1]).then((list) => {
    console.log(list);
  });
}, 800);
你爱我像她 2022-09-19 04:27:33

rxjs

const rxjs = require('rxjs');
const subject = new rxjs.Subject();

const set = new Set();
let timer, data;
function collect(idList) {
  return new Promise((resolve, reject) => {
    idList.forEach((id) => {
      set.add(id);
    });
    subject.subscribe({
      next: (status) => {
        if (status === 1) {
          resolve(
            data
              .filter((item) => idList.includes(item.id))
              .map((item) => item.value)
          );
        }
      },
    });
    clearTimeout(timer);
    timer = setTimeout(() => {
      getValue().then(_data => {
        data = _data;
        subject.next(1);
      });
    }, 300);
  });
}

// 模拟请求
function getValue() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(Array.from(set).map((id) => ({ id, value: id + '' })));
    }, 300);
  });
}

collect([1, 2, 3, 4]).then((list) => {
  console.log(list);
});
collect([1, 3, 5, 7]).then((list) => {
  console.log(list);
});
collect([9, 8, 7, 6]).then((list) => {
  console.log(list);
});
泪是无色的血 2022-09-19 04:27:33
var p = function(){
    const set = new Set();
    let timer;
    let collectionResolveHelper = {
        resolveList:[],
        resolveAll:function(valueList){
            this.resolveList.map((resolveFun)=>{
                resolveFun(valueList);
            });
        }
    }
    function resolveAll(valueList){
        return function(resolveFunction){
            return resolveFunction(valueList);
        }
    }


    function collect(idList) {
      return new Promise((resolve, reject) => {
        idList.forEach((id) => {
          set.add(id);
        });
        //注册缓存resolve回调
        collectionResolveHelper.resolveList.push((valueList)=>{
        resolve(
            valueList
              .filter((item) => idList.includes(item.id))
              .map((item) => item.value)
          );
        });

        clearTimeout(timer);
        timer = setTimeout(async () => {
          const valueList = await getValue();
          //执行后,通过resolveAll方法分发到各自resolve处理函数中
          collectionResolveHelper.resolveAll(valueList);
        }, 300);
      });
    }

    // 模拟请求
    function getValue() {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(Array.from(set).map((id) => ({ id, value: id + '' })));
        }, 300);
      });
    }

    collect([1, 2, 3, 4]).then((list) => {
      console.log(list);
    });
    collect([1, 3, 5, 7]).then((list) => {
      console.log(list);
    });
    collect([9, 8, 7, 6]).then((list) => {
      console.log(list);
    });
}
p();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文