并发异步请求 - 跟踪必要的超时
Concurrent async requests - keep track of necessary timeout
对于 Nominatim 请求,我需要在每个请求之间保持 1500 毫秒的超时。如果多个并发 运行 进程继续触发该函数,我该如何处理?
代码:
osmService:
export const getLocation = async (zipCode, street) => {
if (!zipCode) {
return {
address: null,
cacheHit: false,
};
}
const cacheData = await getAddress(zipCode, street);
if (cacheData && cacheData.length === 1) {
return { address: cacheData[0].address, cacheHit: true };
} if (cacheData && cacheData.length > 1) {
logger.error('Found multiple address, this should not be', zipCode + street);
}
try {
const responseObj = await getNominatimLocation(zipCode, street);
if (responseObj) {
const returnObj = {
...responseObj.address,
lat: responseObj.lat,
lon: responseObj.lon,
displayName: responseObj.display_name,
};
await insertAddress(zipCode, street, null, returnObj);
return {
address: returnObj,
cacheHit: false,
};
}
return {
address: null,
cacheHit: false,
};
} catch (ex) {
logger.error(`Error getting location from ${zipCode} ${street}`, ex);
}
return {
address: null,
cacheHit: false,
};
};
如您所见,我在两者之间有一个缓存层。因此,当请求被缓存命中时,我不需要等待 1500 毫秒。
export const getNominatimLocation = async (zipCode, street, query, retries = 0) => {
if (retries > 5) {
return null;
}
try {
const qs = {
format: 'json',
q: query,
postalcode: zipCode,
addressdetails: 1,
country: 'Deutschland',
street,
'accept-language': 'de',
};
const response = await requestPromise()
.get({
url: OSM_SEARCH,
qs,
timeout: 12000,
headers: {
'User-Agent': 'xxxxxxx',
},
});
return JSON.parse(response)[0];
} catch (ex) {
logger.info(`Nominatim timed out - retry ${retries}`, ex);
await timeout(9000);
return await getNominatimLocation(zipCode, street, query, retries + 1);
}
};
由于 Nominatim 经常超时,我需要执行此递归调用(不需要递归 - 更容易)。
现在假设我有以下想要获取位置的作业(后端引擎)
const jobA = asnyc () => {
const {address, cacheHit} = await getLocation(10243);
if(!cacheHit){
await timeout(1500)
}
}
const jobB = asnyc () => {
const {address, cacheHit} = await getLocation(10245);
if(!cacheHit){
await timeout(1500)
}
}
const startJobs = async () => {
Promise.all([jobA(),jobB()])
console.log('all jobs done');
}
作业部分代表了我当前的代码结构。在我的代码中,作业做的更多(调用其他服务等)。
现在,当我有这个布局时 - 当没有 cacheHit 时,我如何确保在每次 Nominatim 调用之间保持 1500 毫秒?
您可以使用每 1.5 秒才解锁一次的锁:
let lock = Promise.resolve();
let aquireLock = () => (lock = lock.then(() => new Promise(res => setTimeout(res, 1500))));
然后
await aquireLock();
// will only run every 1.5 seconds
对于 Nominatim 请求,我需要在每个请求之间保持 1500 毫秒的超时。如果多个并发 运行 进程继续触发该函数,我该如何处理?
代码:
osmService:
export const getLocation = async (zipCode, street) => {
if (!zipCode) {
return {
address: null,
cacheHit: false,
};
}
const cacheData = await getAddress(zipCode, street);
if (cacheData && cacheData.length === 1) {
return { address: cacheData[0].address, cacheHit: true };
} if (cacheData && cacheData.length > 1) {
logger.error('Found multiple address, this should not be', zipCode + street);
}
try {
const responseObj = await getNominatimLocation(zipCode, street);
if (responseObj) {
const returnObj = {
...responseObj.address,
lat: responseObj.lat,
lon: responseObj.lon,
displayName: responseObj.display_name,
};
await insertAddress(zipCode, street, null, returnObj);
return {
address: returnObj,
cacheHit: false,
};
}
return {
address: null,
cacheHit: false,
};
} catch (ex) {
logger.error(`Error getting location from ${zipCode} ${street}`, ex);
}
return {
address: null,
cacheHit: false,
};
};
如您所见,我在两者之间有一个缓存层。因此,当请求被缓存命中时,我不需要等待 1500 毫秒。
export const getNominatimLocation = async (zipCode, street, query, retries = 0) => {
if (retries > 5) {
return null;
}
try {
const qs = {
format: 'json',
q: query,
postalcode: zipCode,
addressdetails: 1,
country: 'Deutschland',
street,
'accept-language': 'de',
};
const response = await requestPromise()
.get({
url: OSM_SEARCH,
qs,
timeout: 12000,
headers: {
'User-Agent': 'xxxxxxx',
},
});
return JSON.parse(response)[0];
} catch (ex) {
logger.info(`Nominatim timed out - retry ${retries}`, ex);
await timeout(9000);
return await getNominatimLocation(zipCode, street, query, retries + 1);
}
};
由于 Nominatim 经常超时,我需要执行此递归调用(不需要递归 - 更容易)。
现在假设我有以下想要获取位置的作业(后端引擎)
const jobA = asnyc () => {
const {address, cacheHit} = await getLocation(10243);
if(!cacheHit){
await timeout(1500)
}
}
const jobB = asnyc () => {
const {address, cacheHit} = await getLocation(10245);
if(!cacheHit){
await timeout(1500)
}
}
const startJobs = async () => {
Promise.all([jobA(),jobB()])
console.log('all jobs done');
}
作业部分代表了我当前的代码结构。在我的代码中,作业做的更多(调用其他服务等)。
现在,当我有这个布局时 - 当没有 cacheHit 时,我如何确保在每次 Nominatim 调用之间保持 1500 毫秒?
您可以使用每 1.5 秒才解锁一次的锁:
let lock = Promise.resolve();
let aquireLock = () => (lock = lock.then(() => new Promise(res => setTimeout(res, 1500))));
然后
await aquireLock();
// will only run every 1.5 seconds