gpt4 book ai didi

javascript - 没有 RxJS 的异步流控制

转载 作者:行者123 更新时间:2023-11-30 14:40:32 25 4
gpt4 key购买 nike

我正在开发一款移动应用,我希望它是离线优先的。假设我想显示“公司”页面,所以我请求公司数据。

这就是我所做的,我在本地存储(在我的例子中是 indexedDB)中查找公司数据,同时我调用服务器获取相同的数据(以获取潜在的更新)。在每个回调中,我用获取的数据更新 View 。首先从本地数据更新,然后从远程数据更新。

为了避免竞争条件,我在本地存储回调中检查了一个名为“remoteDataAlreadyFetched”的 bool 值(以防远程数据在存储响应之前到达)

我的问题是:我该如何处理?我的 View Controller 中有 2 个单独的 promise (一个用于本地,一个用于远程)?我应该使用 observable 吗?这看起来有点矫枉过正,因为不会有超过 2 个响应(本地和远程)。我错过了什么吗?

非常感谢您的帮助

编辑:

这就是我使用 RxJS 的方式。不知道在这种情况下使用 Observables 是否是一种不好的做法......

public static getOfflineFirstObservable(localCall, remoteCall): Observable<any> {
const data$ = new BehaviorSubject(null);
var hasFetchedRemoteData = false;

localCall().then(localDatas => {
if (!hasFetchedRemoteData) data$.next(localDatas);
});

remoteCall().then(remoteDatas => {
data$.next(remoteDatas);
hasFetchedRemoteData = true;
});

return data$.asObservable();
}

最佳答案

如果您处于离线状态,那么尝试获取远程数据将导致拒绝 promise (使用 promise.race)。如果您要做的只是首先从缓存中获取项目(如果它存在),如果它不尝试将其远程获取,您可以执行以下操作:

const cacheBuilder = promises => fetcher => setFn => getFn => url => {
//using url as key but can be url+JSON.stringify(parameters)+method(GET/POST)
const key = url;
//get from cache first if exist
return getFn(key).catch(()=>{
if(promises[key]){
return promises[key];//return active promise
}
promises[key]=fetcher(url);
return promises[key];

})
.then(
result=>{
if(!promises[key]){//update cache, this will cause requests to server
fetcher(url).then(result=>setFn(key,result)).catch(ignore=>ignore);
}
promises[key]=undefined;
setFn(key,result);
return result;
}
);
}

const cacheFirst = cacheBuilder(
{}//store active promises here
)(
//fetch function (can be $.get or something else)
// I am only using url here but you could use (url,params,method,headers) as well
url=>
//remove "console.log ||" it's to show that multiple active fetches share promises
// asking for fetch("/") multiple times while first time is not resolved
// will not cause multiple requests
console.log("fetching:",url) ||
fetch(url)
.then(response=>response.text())
.then(result=>result.substr(0,10))
)(
//how to set an item in local storage
(key,value)=>{
newStorage = JSON.parse(localStorage.getItem("netCache")||"{}");
newStorage[key]=value;
localStorage.setItem("netCache",JSON.stringify(newStorage));
}
)(
//how to get an item based on key (can be url or url + JSON.stringify(parameters) or url+params+method...)
key=>
Promise.resolve(
JSON.parse(localStorage.getItem("netCache")||"{}")[key] ||
Promise.reject("Not in cache")
)
);

Promise.all([//should not cause multiple requests, should have only one request made
cacheFirst("/"),
cacheFirst("/"),
cacheFirst("/"),
cacheFirst("/")
]).then(
()=>cacheFirst("/")//should come from cache as well, no request made
)

这是一个示例,其中所有实现都在一个函数中,没有传递 fetch、getter 和 setter:

const cacheFirst = (promises => url => {
//using url as key but can be url+JSON.stringify(parameters)+method(GET/POST)
const key = url;
const fetcher = url=>
fetch(url)
.then(response=>response.text())
.then(result=>result.substr(0,10));
const setFn = (key,value)=>{
newStorage = JSON.parse(localStorage.getItem("netCache")||"{}");
newStorage[key]=value;
localStorage.setItem("netCache",JSON.stringify(newStorage));
}
const getFn = key=>
Promise.resolve(
JSON.parse(localStorage.getItem("netCache")||"{}")[key] ||
Promise.reject("Not in cache")
);
//get from cache first if exist
return getFn(key).catch(()=>{
if(promises[key]){
return promises[key];//return active promise
}
promises[key]=fetcher(url);
return promises[key];
})
.then(
result=>{
//update cache if result didn't came from request, this will cause requests to server
if(!promises[key]){
fetcher(url)
.then(result=>setFn(key,result))
.catch(ignore=>ignore);
}
promises[key]=undefined;
setFn(key,result);
return result;
}
);
})({})//IIFE passing in the promises object to store active promises

关于javascript - 没有 RxJS 的异步流控制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49750330/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com