首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Debounce函数的承诺实现

Debounce函数的承诺实现
EN

Stack Overflow用户
提问于 2016-02-05 15:42:45
回答 8查看 30.3K关注 0票数 32

我正在尝试实现一个可以在javascript中使用承诺的with函数。这样,每个调用方都可以使用一个诺言来使用“反跳”函数的结果。到目前为止,我能想到的最好的是:

代码语言:javascript
复制
function debounce(inner, ms = 0) {
  let timer = null;
  let promise = null;
  const events = new EventEmitter();  // do I really need this?

  return function (...args) {
    if (timer == null) {
      promise = new Promise(resolve => {
        events.once('done', resolve);
      });
    } else {
      clearTimeout(timer);
    }

    timer = setTimeout(() => {
      events.emit('done', inner(...args));
      timer = null;
    }, ms);

    return promise;
  };
}

理想情况下,我希望实现这个实用程序函数,而不引入对EventEmitter的依赖(或者实现我自己的基本版本的EventEmitter),但我想不出有什么方法可以做到这一点。有什么想法吗?

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2016-02-05 16:02:35

我找到了一种更好的方法来实现这个承诺:

代码语言:javascript
复制
function debounce(inner, ms = 0) {
  let timer = null;
  let resolves = [];

  return function (...args) {    
    // Run the function after a certain amount of time
    clearTimeout(timer);
    timer = setTimeout(() => {
      // Get the result of the inner function, then apply it to the resolve function of
      // each promise that has been created since the last time the inner function was run
      let result = inner(...args);
      resolves.forEach(r => r(result));
      resolves = [];
    }, ms);

    return new Promise(r => resolves.push(r));
  };
}

我仍然欢迎一些建议,但新的实现回答了我最初的问题,即如何在不依赖EventEmitter (或类似的东西)的情况下实现这个函数。

票数 36
EN

Stack Overflow用户

发布于 2017-06-22 07:06:14

我来到这里是因为我想得到承诺的返回值,但是退出underscore.js却返回了undefined。最后,我在leading=true中使用了leading=true版本。它适用于我的情况,因为我不在乎执行是导致还是落后。

https://lodash.com/docs/4.17.4#debounce

代码语言:javascript
复制
_.debounce(somethingThatReturnsAPromise, 300, {
  leading: true,
  trailing: false
})
票数 12
EN

Stack Overflow用户

发布于 2021-07-02 15:39:16

解决一个承诺,取消其他

我所见过的许多实现使问题复杂化或存在其他卫生问题。在这篇文章中,我们将编写我们自己的debounce。这项实施将-

  • 在任何给定时间最多有一项承诺尚未兑现(每项已取消的任务)
  • 通过正确取消未执行的承诺来阻止内存泄漏
  • 只解决最新的承诺
  • 用实时代码演示演示正确的行为

我们用两个参数编写debounce,一个是要退出的task,另一个是延迟的毫秒,ms。我们为它的本地状态引入了一个局部绑定,t -

代码语言:javascript
复制
function debounce (task, ms) {
  let t = { promise: null, cancel: _ => void 0 }
  return async (...args) => {
    try {
      t.cancel()
      t = deferred()
      await t.promise
      await task(...args)
    }
    catch (_) { /* prevent memory leak */ }
  }
}

我们依赖于一个可重用的deferred函数,它创建了一个以ms毫秒为单位解决问题的新承诺。它引入了两个本地绑定,promise本身,以及cancel It的能力-

代码语言:javascript
复制
function deferred (ms) {
  let cancel, promise = new Promise((resolve, reject) => {
    cancel = reject
    setTimeout(resolve, ms)
  })
  return { promise, cancel }
}

单击计数器示例

在第一个例子中,我们有一个按钮来统计用户的点击。事件侦听器使用debounce附加,因此计数器只能在指定的持续时间后递增-

代码语言:javascript
复制
// debounce, deferred
function debounce (task, ms) { let t = { promise: null, cancel: _ => void 0 }; return async (...args) => { try { t.cancel(); t = deferred(ms); await t.promise; await task(...args); } catch (_) { console.log("cleaning up cancelled promise") } } }
function deferred (ms) { let cancel, promise = new Promise((resolve, reject) => { cancel = reject; setTimeout(resolve, ms) }); return { promise, cancel } }

// dom references
const myform = document.forms.myform
const mycounter = myform.mycounter

// event handler
function clickCounter (event) {
  mycounter.value = Number(mycounter.value) + 1
}

// debounced listener
myform.myclicker.addEventListener("click", debounce(clickCounter, 1000))
代码语言:javascript
复制
<form id="myform">
<input name="myclicker" type="button" value="click" />
<output name="mycounter">0</output>
</form>

实时查询示例“自动完成”

在第二个例子中,我们有一个带有文本输入的表单。我们的search查询使用debounce -

代码语言:javascript
复制
// debounce, deferred
function debounce (task, ms) { let t = { promise: null, cancel: _ => void 0 }; return async (...args) => { try { t.cancel(); t = deferred(ms); await t.promise; await task(...args); } catch (_) { console.log("cleaning up cancelled promise") } } }
function deferred (ms) { let cancel, promise = new Promise((resolve, reject) => { cancel = reject; setTimeout(resolve, ms) }); return { promise, cancel } }

// dom references
const myform = document.forms.myform
const myresult = myform.myresult

// event handler
function search (event) {
  myresult.value = `Searching for: ${event.target.value}`
}

// debounced listener
myform.myquery.addEventListener("keypress", debounce(search, 1000))
代码语言:javascript
复制
<form id="myform">
<input name="myquery" placeholder="Enter a query..." />
<output name="myresult"></output>
</form>

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35228052

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档