防止并发ajax请求,让它们等待



我的客户端Javascript应用程序需要来自服务器端的特定数据结构("list"(。应用程序中的几个不同位置需要访问列表。在启动时,这些地方都会发出请求,这会导致对同一数据结构向服务器发出多个并发请求。

我只想向服务器发出一个请求,并让所有的请求者只得到一个承诺,在请求返回时解决。

我认为方法是创建一个promise数组或堆栈。如果第一个请求正在运行中,那么随后的每个请求都会创建一个promise并将其添加到堆栈中。当响应返回时,系统运行堆栈并解析所有的promise和结果。

问题是,我无法找到正确的语法来实现这一点。这就是我目前所拥有的:

let lists = [];
let loading = false;
let promises = [];
function getLists() {
if (lists.length > 0) {
// return cached copy
return Promise.resolve(lists);
}
/*
This method can get called several times in quick succession on startup.
To prevent sending multiple requests to the server, we maintain 
a stack of promises. If there is already a request in-flight, then just
add a promise to the stack and return it. Then resolve all promises
in the stack when the request returns.
*/
let prom = new Promise();  // BAD, NOT ALLOWED
promises.push(prom);
if (!loading) {
callListsApi(); // async call, resolves promises
}
return prom;
}
function callListsApi() {
loading = true;
axios.get("/lists").then(
response => {
loading = false;
if (!response.data || response.data.length == 0) {
lists = [];
} else {
lists = response.data;
}
for (let i = 0; i < promises.length; i++) {
promises[i].resolve(lists); // give all the callers their lists
}
promises = [];
},
error => {
loading = false;
util.handleAxiosError(error);
let msg = util.getAxiosErrorText(error);
for (let i = 0; i < promises.length; i++) {
promises[i].reject(msg);
}
promises = [];
}
);
}

这不起作用,因为如果不在其中放入某种executor函数,就无法创建一个空的Promise((

我该如何重写它才能工作?

想明白了。答案不是创造一堆承诺。这只是一次又一次地向每个请求者返回相同的承诺。我们有一个主要承诺,只有当请求在飞行中时才存在。这要简单得多。

let lists = [];
let listPromise = null;
function getLists() {
if (lists.length > 0) {
// return cached copy
return Promise.resolve(lists);
}
if (listPromise != null) {
// if we get here, then there is already a request in-flight
return listPromise;
}
listPromise = callListsApi();
return listPromise;
}
function callListsApi() {
return axios.get("/lists").then(
response => {
if (!response.data || response.data.length == 0) {
lists = [];
} else {
lists = response.data;
}
listPromise = null;
return lists;
},
error => {
util.handleAxiosError(error);
listPromise = null;
return util.getAxiosErrorText(error);
}
);
}

最新更新