Javascript 累积ID以发出单个ajax请求

Javascript 累积ID以发出单个ajax请求,javascript,ajax,promise,debounce,Javascript,Ajax,Promise,Debounce,我需要在多个地方发出ajax请求,以获取与某些ID对应的项。然而,我只想通过累积这些ID并取消发出ajax请求的实际方法来发出一个请求……到目前为止,我已经提出了这段代码,但它感觉很难看/不可重用 有没有更简单/推荐的方法可以在不共享resolve/promise变量的情况下获得类似的结果 这里有一个 const fakeData=[{ id:1, 姓名:“富” }, { id:2, 名称:“酒吧” }, { id:3, 名称:“baz” } ]; 让idsToFetch=[]; 让getIt

我需要在多个地方发出ajax请求,以获取与某些ID对应的项。然而,我只想通过累积这些ID并取消发出ajax请求的实际方法来发出一个请求……到目前为止,我已经提出了这段代码,但它感觉很难看/不可重用

有没有更简单/推荐的方法可以在不共享
resolve
/
promise
变量的情况下获得类似的结果

这里有一个

const fakeData=[{
id:1,
姓名:“富”
},
{
id:2,
名称:“酒吧”
},
{
id:3,
名称:“baz”
}
];
让idsToFetch=[];
让getItemsPromise、resolve、reject;
const fetchItems=u.debounce(()=>{
log('fetching items…');
const currentResolve=解析;
const currentReject=拒绝;
//模拟ajax请求
setTimeout(函数(){
const result=idsToFetch.map((id)=>fakeData.find(item=>item.id==id));
当前解决(结果);
}, 400);
getItemsPromise=resolve=reject=null;
}, 500);
函数getItems(ID){
idsToFetch=ids.filter((id)=>!idsToFetch.includes(id)).concat(idsToFetch);
如果(!getItemsPromise){
getItemsPromise=新承诺((\u resolve,\u reject)=>{
决心=_决心;
拒绝=_拒绝;
});
}
fetchItems();
返回getItemsPromise
。然后((res)=>{
return res.filter((item)=>id.includes(item.id));
})
}
设置超时(()=>{
log('first request start');
getItems([1])。然后(res=>console.log('first result:',res));
}, 100);
设置超时(()=>{
log(“第二次请求启动”);
getItems([1,2]),然后(res=>console.log('secondresult:',res));
}, 200)
设置超时(()=>{
log(“第三次请求启动”);
getItems([1,3]),然后(res=>console.log('third result:',res));
},300)

我能够通过创建一个函数生成器来封装逻辑,该函数生成器包含前两个函数,如下所示:

const fakeData=[{
id:1,
姓名:“富”
},
{
id:2,
名称:“酒吧”
},
{
id:3,
名称:“baz”
}
];
函数makeGetter(fetchFunc,debounceTime=400){
让idsToFetch=[];
让getItemsPromise、resolve、reject;
const fetchItems=u.debounce(()=>{
log('fetching items…');
const currentResolve=解析;
const currentReject=拒绝;
const current idsToFetch=idsToFetch;
Promise.resolve(fetchFunc(currentIdsToFetch))
。然后(res=>currentResolve(res))
.catch(err=>currentReject(err));
getItemsPromise=resolve=reject=null;
idsToFetch=[];
},去BounceTime);
常量getItems=(ID)=>{
idsToFetch=ids.filter((id)=>!idsToFetch.includes(id)).concat(idsToFetch);
如果(!getItemsPromise){
getItemsPromise=新承诺((\u resolve,\u reject)=>{
决心=_决心;
拒绝=_拒绝;
});
}
const currentPromise=getItemsPromise;
fetchItems();
回报承诺
。然后((res)=>{
return res.filter((item)=>id.includes(item.id));
})
}
归还物品;
}
const getItems=makeGetter((id)=>{
//模拟ajax请求
返回新承诺((解决、拒绝)=>{
setTimeout(函数(){
const result=ids.map((id)=>fakeData.find(item=>item.id==id));
决心(结果);
}, 400);
})
});
设置超时(()=>{
log('first request start');
getItems([1])。然后(res=>console.log('first result:',res));
}, 100);
设置超时(()=>{
log(“第二次请求启动”);
getItems([1,2]),然后(res=>console.log('secondresult:',res));
}, 200)
设置超时(()=>{
log(“第三次请求启动”);
getItems([1,3]),然后(res=>console.log('third result:',res));
},300)

我发现编写行为完全由我控制的
debounce()
函数比依赖库方法更简单

特别是,我特意设计了一种与问题中不同的去盎司行为,即(如果我理解正确的话)第一个,也可能是唯一的快速序列请求必须等待去盎司延迟到期

在下面的代码中,不是原始的
getItemsPromise
a
debouncePromise
用于表示一个去盎司周期,在此期间,取回被抑制,请求数据被允许累积。从静态状态(无论何时
debouncePromise===null
),下一个
fetch()
调用将尽快获取数据(下一个勾号)。只有第二次和随后的调用才会解除抖动,直到解除抖动周期到期,
debounce()
实例返回其静态状态。我认为,这是一个与原始模式一样有效的“去盎司”范式,而且可以说更好。(如果不是,则可以稍微修改
fetch()
,以提供原始行为)

除此之外,差异很小:

  • 避免了混乱的外部化
    解决
    拒绝
  • 在尝试保持
    debounce()
    泛型时,除了
    fetcher
    delay
    之外,还会传递
    resultsFilter
    函数
代码中的进一步注释

function debounce(fetcher, resultsFilter, delay) {
    let idsToFetch = [],
        debouncePromise = null;
    function reset() { // utility funtion - keeps code below clean and DRY
        let idsToFetch_ = idsToFetch;
        idsToFetch = [];
        return idsToFetch_;
    }
    function fetch(ids) {
        idsToFetch = idsToFetch.concat(ids.filter(id => !idsToFetch.includes(id))); // swapped around so as not to reverse the order.
        if (!debouncePromise) {
            // set up the debounce period, and what is to happen when it expires.
            debouncePromise = new Promise(resolve => {
                setTimeout(resolve, delay);
            }).then(() => {
                // on expiry of the debounce period ...
                debouncePromise = null; // ... return to quiescent state.
                return fetcher(reset()); // ... fetch (and deliver) data for all request data accumulated in the debounce period.
            });
            // *** First call of this debounce period - FETCH IMMEDIATELY ***
            return Promise.resolve(reset()).then(fetcher); // (1) ensure fetcher is called asynchronously (as above). (2) resultsFilter is not necessary here.
        } else {
            return debouncePromise.then(res => resultsFilter(ids, res)); // when debouncePromise exists, return it with chained filter to give only the results for these ids.
        }
    }
    return fetch;
}
示例用法:

function fetchItems(ids) {
    const fakeData = [
        { 'id': 1, 'name': 'foo' },
        { 'id': 2, 'name': 'bar' },
        { 'id': 3, 'name': 'baz' },
        { 'id': 4, 'name': 'zaz' }
    ];
    if (ids.length > 0) {
        return new Promise(resolve => { // simulate ajax request
            setTimeout(resolve, 400);
        }).then(() => {
            return ids.map(id => fakeData.find(item => item.id == id));
        });
    } else {
        return Promise.resolve([]);
    }
}
function filterResults(ids, results) {
    return results.filter(item => ids.includes(item.id));
}

// ******************************************************
let getItems = debounce(fetchItems, filterResults, 500);
// ******************************************************

setTimeout(() => {
    console.log('first request start');
    getItems([1]).then(res => console.log('first result:', res));
}, 100);
setTimeout(() => {
    console.log('second request start');
    getItems([1, 2]).then(res => console.log('second result:', res));
}, 200);
setTimeout(() => {
    console.log('third request start');
    getItems([1, 3]).then(res => console.log('third result:', res));
}, 300);
setTimeout(() => {
    console.log('fourth request start');
    getItems([1, 4]).then(res => console.log('fourth result:', res));
}, 2000);

像这样的问题,在代码运行的地方,你正在寻找优化的地方,更适合在上面提问。我也会在那里检查,谢谢。应该是可能的,而不必外部化
解决
拒绝
@Roamer-1888。请随意添加一个说明如何解决的答案。很好,感谢您抽出时间来解决这个问题。如果我没有弄错的话,您已经实现了节流而不是去Bouncing,对吗?我认为我的范例基本上与您的范例相同,除了每个“去Bou”中的初始请求