事先为模棱两可的标题道歉。
为了更好地解释这个问题-fetch-form-data.js
中有两个函数看起来像...
let cachedBaseUrl;
const getBaseUrl = () => {
if (cachedBaseUrl) return Promise.resolve(cachedBaseUrl)
return fetch('https://some-baseurl-endpoint.com')
.then(baseUrl => {
cachedBaseUrl = baseUrl
return baseUrl
});
}
const getFormData = formId =>
getBaseUrl()
.then(baseUrl => fetch('https://form-data-endpoint.com'))
module.exports = {
getFormData
}
getFormData
在其他位置的循环中被导出并调用了数百次。问题是getFormData
取决于getBaseUrl
,因此数百次调用getFormData
也会调用getBaseUrl
数百次,这经常出错,因为我猜到baseUrl端点没有不喜欢这么快就被击中。
相反,我想确保getBaseUrl
仅被击中一次,并让所有后续getFormData
在getBaseUrl
上都调用“ wait”,然后再继续前进。
一种解决方案是在使用getBaseUrl
的任何地方导出getFormData
和getFormData
,等待getBaseUrl
,然后根据需要多次调用getFormData
。像...
async () => {
const baseUrl = await getBaseUrl();
const formData = [];
for (let form of forms) {
formData.push(getFormData(form));
}
await Promise.all(formData);
...
}
但是,getFormData
的用法遍布整个代码库。最好像当前实现一样简单地提取getBaseUrl
并仅公开getFormData
,但解决“等待”所有后续getFormData
调用直到至少第一个{{ 1}}呼叫已解决。
我微不足道的尝试是缓存baseUrl(如上面的代码块所示),但这并没有“停止”随后的getBaseUrl
个紧接着的调用,后者又调用了getBaseUrl
个,因为还没有缓存任何内容
我将如何实现这样的目标?
答案 0 :(得分:3)
尝试一下
let cachedBaseUrl;
const getBaseUrl = () => {
if (cachedBaseUrl) return cachedBaseUrl
return cachedBaseUrl = new Promise((resolve, reject) =>
fetch('https://some-baseurl-endpoint.com')
.then(BaseUrl => { cachedBaseUrl = undefined; resolve(BaseUrl) })
.catch(() => { cachedBaseUrl = undefined; reject() })
);
}
您需要在第一个请求完成之前停止getBaseUrl()
发送其他请求。因此,您需要一个该请求的承诺,而不是Promise.resolve(constant)
。
请求完成后,您可以使用resolve/reject
设置其结果并重置cachedBaseUrl
,以便您可以通过if
并重试。
由您决定重置逻辑。您可以不停地不断地,顺序地(如现在这样)或不时地获取baseurl-endpoint,那么您将不得不调用SetTimeout(interval, () => cachedBaseUrl = undefined)
而不是cachedBaseUrl = undefined
。或者做你想做的事。
答案 1 :(得分:1)
也要缓存您的诺言。
let cachedBaseUrl, cachedPromise;
const getBaseUrl = () => {
if (cachedBaseUrl) return Promise.resolve(cachedBaseUrl)
if (cachedPromise) return cachedPromise;
cachedPromise = fetch('https://some-baseurl-endpoint.com')
.then(baseUrl => {
cachedBaseUrl = baseUrl
return baseUrl
});
return cachedPromise;
}
const getFormData = formId =>
getBaseUrl()
.then(baseUrl => fetch('https://form-data-endpoint.com'))
module.exports = {
getFormData
}
答案 2 :(得分:0)
一次致电getBaseUrl()
并保存您从中获得的承诺。然后在getFormData()
中,根据已保存的承诺调用then
。
const getBaseUrl = () => ...
const baseUrlPromise = getBaseUrl()
const getFormData = formId =>
baseUrlPromise
.then(...)
在一个承诺上多次使用.then(...)
可以做出多个依赖于此的承诺。
如果cachedBaseUrl
没什么用,可以将其删除,因为解析后的值将保存为baseUrlPromise
的一部分。
答案 3 :(得分:0)
您的缓存解决方案是一个不错的开始,通过缓存未完成的promise,我认为它可以很好地解决问题。
let cachedBaseUrl;
const getBaseUrl = () => {
if (cachedBaseUrl) return Promise.resolve(cachedBaseUrl)
return cachedBaseUrl = fetch('https://some-baseurl-endpoint.com');
}
const getFormData = formId =>
getBaseUrl()
.then(baseUrl => fetch('https://form-data-endpoint.com'))
module.exports = {
getFormData
}