我正在尝试实现一个可以在javascript中使用承诺的with函数。这样,每个调用方都可以使用一个诺言来使用“反跳”函数的结果。到目前为止,我能想到的最好的是:
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),但我想不出有什么方法可以做到这一点。有什么想法吗?
发布于 2016-02-05 16:02:35
我找到了一种更好的方法来实现这个承诺:
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 (或类似的东西)的情况下实现这个函数。
发布于 2017-06-22 07:06:14
我来到这里是因为我想得到承诺的返回值,但是退出underscore.js却返回了undefined。最后,我在leading=true中使用了leading=true版本。它适用于我的情况,因为我不在乎执行是导致还是落后。
https://lodash.com/docs/4.17.4#debounce
_.debounce(somethingThatReturnsAPromise, 300, {
leading: true,
trailing: false
})发布于 2021-07-02 15:39:16
解决一个承诺,取消其他
我所见过的许多实现使问题复杂化或存在其他卫生问题。在这篇文章中,我们将编写我们自己的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 */ }
}
}我们依赖于一个可重用的deferred函数,它创建了一个以ms毫秒为单位解决问题的新承诺。它引入了两个本地绑定,promise本身,以及cancel It的能力-
function deferred (ms) {
let cancel, promise = new Promise((resolve, reject) => {
cancel = reject
setTimeout(resolve, ms)
})
return { promise, cancel }
}单击计数器示例
在第一个例子中,我们有一个按钮来统计用户的点击。事件侦听器使用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))<form id="myform">
<input name="myclicker" type="button" value="click" />
<output name="mycounter">0</output>
</form>
实时查询示例“自动完成”
在第二个例子中,我们有一个带有文本输入的表单。我们的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))<form id="myform">
<input name="myquery" placeholder="Enter a query..." />
<output name="myresult"></output>
</form>
https://stackoverflow.com/questions/35228052
复制相似问题