我对debounce axios请求的实现将promise永远保留在待处理状态,有没有更好的方法? [英] My implementation of debounce axios request left the promise in pending state forever, is there a better way?

查看:590
本文介绍了我对debounce axios请求的实现将promise永远保留在待处理状态,有没有更好的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个简单的反跳函数,且立即数始终为true。

无需诉诸于lodash并借助有人可以解释 debounce功能吗? JavaScript中的函数,我实现了以下代码,

I need a simple debounce function with immediate always true.
Without resorting to lodash and with the help of Can someone explain the "debounce" function in Javascript , I implemented it as following,

function debounce(func, wait) {
    var timeout;
    return function() {
        if (!timeout) func.apply(this, arguments);
        clearTimeout(timeout);
        timeout = setTimeout(()=>{timeout = null}, wait);
    };
};

它可以按预期工作,直到我需要取消axios请求的抖动为止。假设我有一个防抖动的axios方法,我希望调用方法像往常一样,这意味着我的防抖动的axios方法应该返回我相信的承诺。

It works as expected until I need to debounce axios request. Assumed I have a debounced axios method, I would like the calling method to be as usual, which means my debounced axios method should return promise I believe.

   //the calling method should not change   
   debounced_axios().then(res => {...}).catch(err => {...}) 

原始防抖动实现的本质是仅在等待时间内运行func 一次,但是我如何在等待时间内返回一个承诺?

The essence of original debounce implementation is to just run func once in a wait timeframe, but how do I just return one promise in a wait timeframe ?

然后我想出了以下解决方案

Then I came up with the following solution

all_timers = {}
function debounce_axios(input, wait) {
    return new Promise((resolve, reject) => {
        let timer = all_timers.[input] //check if it is a repeated request, pseudo code
        if (!timer) {
            axios(input).then(res=>{
                resolve(res)
            }).catch(err => {
                reject(err)
            })
        }
        clearTimeout(timer);
        timer = setTimeout(()=>{timer = null}, wait);
        all_timers[input] = timer
    };
};

所以我的debounce_axios的本质是让诺言保持待定状态以供重复请求。调用方法 debounced_axios()。then(res => {...})。catch(err => {...})无需更改。

So the essence of my debounce_axios is to let the promise stay in pending state for the repeated request.Then the calling method debounced_axios().then(res => {...}).catch(err => {...}) does not need to change.

答案在这里是JavaScript永远待定的诺言不好吗?说应该没有副作用。

The answer here Are JavaScript forever-pending promises bad? said "There should be no side effect."

但是我仍然不是100%肯定要诺言永远的等待。

But I am still not 100% sure about letting a promise stay in pending forever.

另一个问题是承诺反模式建议不要创建不必要的承诺。

The other question is that Promise Anti patterns suggested not creating unnecessary promise. But in my case creating a new promise seems necessary.

总而言之,有没有一种简单的方法可以对axios请求(或任何请求返回promise)进行反跳?

In a nutshell is there a simple to way to debounce axios request (or any request returns promise) ?

推荐答案


但是,我仍然不确定百分百地永远保留未决。 / p>

But I am still not 100% sure about letting a promise stay in pending forever.

我同意这不是一个好主意。更好的方法是将整个promise链移到去抖动函数中。

I agree that it's not a good idea. A better approach would be to move the entire promise chain inside the debounced function.

另一种选择是当去抖动调用未触发新请求时返回缓存的值。这将解决您始终需要返回承诺的问题:

Another option would be to return a cached value when the debounced call does not trigger a new request. This would solve your problem that you always need to return a promise:

function debounce(func, wait) {
    var timeout, value;
    return function() {
        if (!timeout) value = func.apply(this, arguments);
        clearTimeout(timeout);
        timeout = setTimeout(() => {
            timeout = value = null;
        }, wait);
        return value;
    };
}

当然,这意味着在某些情况下,多个然后处理程序将在您的请求完成时调用。

Of course that would mean that in some cases, multiple then handlers will be called when your request finishes. It depends on your application whether that is a problem or just superfluous work.


另一个问题是Promise Anti模式建议不要创建不必要的承诺,这取决于您的应用程序。 。但是在我看来,创建新的承诺似乎是必要的。

The other question is that Promise Anti patterns suggested not creating unnecessary promise. But in my case creating a new promise seems necessary.

只有一个承诺是必要的:创建从未解决的承诺。您可以这样写:

Only one promise is necessary: when you create the never-resolved one. You can write that as

function debounce(func, wait) {
    var timeout;
    const never = new Promise(resolve => {/* do nothing*/});
    return function() {
        const result = timeout ? never : func.apply(this, arguments);
        clearTimeout(timeout);
        timeout = setTimeout(() => {
            timeout = null;
        }, wait);
        return result;
    };
}

或者至少避免使用。然后(解决) .catch(reject)部分。最好写

Or at least avoid the .then(resolve).catch(reject) part. Better write

function debounce(func, wait) {
    var timeout;
    return function() {
        return new Promise(resolve => {
            if (!timeout) resolve(func.apply(this, arguments));
//                        ^^^^^^^
            clearTimeout(timeout);
            timeout = setTimeout(() => {
                timeout = null;
            }, wait);
        });
    };
}

如果尚未超时,您是否应该考虑拒绝承诺发生(以便调用代码可以处理拒绝),您也不需要新的承诺

And should you consider to reject the promise in case that the timeout has not yet occurred (so that the calling code can handle the rejection), you don't need new Promise either:

function debounce(func, wait) {
    var timeout;
    return function() {
        const result = timeout
          ? Promise.reject(new Error("called during debounce period"))
          : Promise.resolve(func.apply(this, arguments));
        clearTimeout(timeout);
        timeout = setTimeout(() => {
            timeout = null;
        }, wait);
        return result;
    };
}

这篇关于我对debounce axios请求的实现将promise永远保留在待处理状态,有没有更好的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆