Chr*_*ris 16 javascript promise
我正在尝试实现一个与javascript中的promise一起使用的去抖函数.这样,每个调用者都可以使用Promise消耗"debounced"函数的结果.这是迄今为止我能够提出的最好的:
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;
};
}
Run Code Online (Sandbox Code Playgroud)
理想情况下,我想实现这个实用程序函数而不引入依赖于EventEmitter(或实现我自己的基本版本的EventEmitter),但我想不出办法.有什么想法吗?
Chr*_*ris 28
我找到了一个更好的方法来实现这个承诺:
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));
};
}
Run Code Online (Sandbox Code Playgroud)
我仍然欢迎建议,但新的实现回答了我关于如何实现这个函数的原始问题,而不依赖于EventEmitter(或类似的东西).
小智 10
这是我的实现,只有间隔中的最后一个调用会得到解决。在克里斯的解决方案中,所有呼叫将在它们之间延迟解决,这很好,但是有时我们只需要解决最后一个呼叫。如果我错了纠正我。
function debounce(f, interval) {
let timer = null;
return (...args) => {
clearTimeout(timer);
return new Promise((resolve) => {
timer = setTimeout(
() => resolve(f(...args)),
interval,
);
});
};
}
Run Code Online (Sandbox Code Playgroud)
解决一个承诺,取消其他承诺
我见过的许多实现都使问题过于复杂或存在其他卫生问题。在这篇文章中,我们将编写我们自己的debounce. 此实施将 -
我们debounce用它的两个参数来编写,即task去抖和延迟的毫秒数ms。我们为其本地状态引入一个本地绑定,t-
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 */ }
}
}
Run Code Online (Sandbox Code Playgroud)
我们依赖于一个可重用的deferred函数,它创建了一个在几毫秒内解析的新承诺ms。它引入了两个本地绑定,它promise本身,以及它的能力cancel-
function deferred (ms) {
let cancel, promise = new Promise((resolve, reject) => {
cancel = reject
setTimeout(resolve, ms)
})
return { promise, cancel }
}
Run Code Online (Sandbox Code Playgroud)
点击计数器示例
在第一个示例中,我们有一个用于计算用户点击次数的按钮。事件侦听器使用 附加debounce,因此计数器仅在指定的持续时间后递增 -
// 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))Run Code Online (Sandbox Code Playgroud)
<form id="myform">
<input name="myclicker" type="button" value="click" />
<output name="mycounter">0</output>
</form>Run Code Online (Sandbox Code Playgroud)
实时查询示例,“自动完成”
在第二个示例中,我们有一个带有文本输入的表单。我们的search查询附有debounce-
// 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))Run Code Online (Sandbox Code Playgroud)
<form id="myform">
<input name="myquery" placeholder="Enter a query..." />
<output name="myresult"></output>
</form>Run Code Online (Sandbox Code Playgroud)
我登陆这里是因为我想获得Promise的返回值,但是在underscore.js中反跳才返回了undefined。我最终使用lodash带有Leading = true的版本。它适用于我的情况,因为我不在乎执行是领先还是落后。
https://lodash.com/docs/4.17.4#debounce
_.debounce(somethingThatReturnsAPromise, 300, {
leading: true,
trailing: false
})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
13075 次 |
| 最近记录: |