在本文中,我们将为您详细介绍多个顺序fetch的相关知识,并且为您解答关于承诺的疑问,此外,我们还会提供一些关于Cache与Fetch(二)、django的prefetch()、Fetch(原生)的简
在本文中,我们将为您详细介绍多个顺序fetch的相关知识,并且为您解答关于承诺的疑问,此外,我们还会提供一些关于Cache与Fetch(二)、django 的 prefetch()、Fetch(原生)的简单使用、Fetch()-如何使用重定向显示位置页面:关注的有用信息。
本文目录一览:多个顺序fetch()承诺(fetch顺序无效)
我必须做一个序列的fetch()
承诺:我一次只有1个网址,这意味着只有1个fetch()
诺言。每次我收到一个json时,其中一个都包含另一个json的网址,因此我必须做出另一个fetch()
承诺。
我可以处理多个诺言,但是在这种情况下,我做不到Promise.all()
,因为我没有所有的URL,只有一个。
这个例子不起作用,全部冻结。
function fetchNextJson(json_url) { return fetch(json_url, { method: ''get'' }) .then(function(response) { return response.json(); }) .then(function(json) { console.log(json); return json; }) .catch(function(err) { console.log(''error: '' + error); });}function getItems(next_json_url) { if (!(next_json_url)) return; get_items = fetchNextJson(next_json_url); interval = $q.when(get_items).then(function(response) { console.log(response); next_json_url = response.Pagination.NextPage.Href; }); getItems(next_json_url);}var next_json_url = ''http://localhost:3000/one'';getItems(next_json_url);
答案1
小编典典您可以使用递归
function fetchNextJson(json_url) { return fetch(json_url, { method: ''get'' }) .then(function(response) { return response.json(); }) .then(function(json) { results.push(json); return json.Pagination.NextPage.Href ? fetchNextJson(json.Pagination.NextPage.Href) : results }) .catch(function(err) { console.log(''error: '' + error); });}var next_json_url = ''http://localhost:3000/one'';var results = [];fetchNextJson(json_url).then(function(res) { console.log(res)})
Cache与Fetch(二)
这两天一直百思不得其解的问题终于解决了,这个问题如下:
通过HQL:“select distinct forumGroup from ForumGroup as forumGroup left join fetch forumGroup.forums”查询所有ForumGroup,并将它们的Forum一并抓取出来。查询启用了查询缓存,ForumGroup和Forum都被映射为可缓存的。
第一次执行时,自然不会命中,生成了如下SQL:
/* select
distinct forumGroup
from
ForumGroup as forumGroup
left join
fetch forumGroup.forums */ select
distinct forumgroup0_.id as id3_0_,
forums1_.id as id2_1_,
forumgroup0_.creationTime as creation2_3_0_,
forumgroup0_.description as descript3_3_0_,
forumgroup0_.modifiedTime as modified4_3_0_,
forumgroup0_.name as name3_0_,
forums1_.creationTime as creation2_2_1_,
forums1_.description as descript3_2_1_,
forums1_.groupId as groupId2_1_,
forums1_.modifiedTime as modified4_2_1_,
forums1_.name as name2_1_,
forums1_.groupId as groupId0__,
forums1_.id as id0__
from
ForumGroup forumgroup0_
left outer join
Forum forums1_
on forumgroup0_.id=forums1_.groupId
第二次执行时,按理是应该命中,不会有任何SQL生成,但是实际结果却是:
DEBUG [13178395@qtp-12191562-0] StandardQueryCache.get(142) | returning cached query results
/* load one-to-many oobbs.domainmodel.forum.ForumGroup.forums */ select
forums0_.groupId as groupId1_,
forums0_.id as id1_,
forums0_.id as id2_0_,
forums0_.creationTime as creation2_2_0_,
forums0_.description as descript3_2_0_,
forums0_.groupId as groupId2_0_,
forums0_.modifiedTime as modified4_2_0_,
forums0_.name as name2_0_
from
Forum forums0_
where
forums0_.groupId=?
.
.
.
重复出现上述SQL.
分析上面的日志我发现:1.查询已经命中,这一点是确认的。2.重复出现的SQL是在迭代ForumGroup中试图访问它的Fourm集合时生成的,这是一个典型的N+1次查询问题。
这里让我迷惑的是:Forum被标记为了可缓存,明明是被Fetch出来的,在第一次查询时它们就被加载出来并进入到二级缓存了,为什么在第二次第三次查询时却找不到这些对象,还要重新查数据库呢?经过排查发现,在ForumGroup的Forum集合字段上没有将该集合配制为可缓存。这样,虽然第一次这些Forum都被抓取出来并进入了二级缓存,但是ForumGroup对象的forums集合(一个存放Forum的ID的集合,不是Forum对象的集合)在上次查询时就没有进入二级缓存,现在,这些集合没有保存forum的ID(在第一次查询的结果集中是有这些ID的,但是因为这个forums集合没有配为可缓存的,所以在ForumGroup对象进入二级缓存时,这些forum集合的信息就被舍弃了)。 这样,下一次查询时,虽然查询命中,但是查询结果中的ForumGroup的fourms集合是空的,因而会重新生成SQL查询。
另外,通过Debug,我发现,Query Cache缓存一个查询,其key就不多说了,在log中都会打出,其Value很有意思。上面的这个查询这的value是[5228208135548928, 1, 1, 2],第一个数据是一个时间戳,第二,三,四就是ForumGroup的ID。因为做过表连接,所以ForumGroup_1重复出现了一次。Forum的ID并没有在缓存的value中。由此可以确定,Query Cache只缓存结果集中对象的ID。被Fetch出来的Forum不被视为结果集的一部分,因而没有出现在结果集中。
还会有一些相似的问题可能会出现,比如:
相同条件第一次 list的时候,因为查询缓存中找不到,不管class缓存是否存在数据,总是发送一条sql语句到数据库获取全部数据,然后填充查询缓存和class缓存。但是第二次执行的时候,问题就来了,如果你的class缓存的超时时间比较短,现在class缓存都超时了,但是查询缓存还在,那么list方法在获取id串以后,将会一个一个去数据库load( N+1次 查询问题 )!因此,class缓存的超时时间一定不能短于查询缓存设置的超时时间!如果还设置了发呆时间的话,保证class缓存的发呆时间也大于查询缓存的生存时间。这里还有其他情况,比如class缓存被程序强制evict了,这种情况就请自己注意了。如果以上问题没有处理好,就必然会出现N+1次查询问题。
通过这个问题,总结两点:
1.查询缓存只保存储查询结果集中对象的ID,对象的实例存放在二级缓存中。这种缓存格局可能有两种不一致的情况发生:一.二级缓存中有实体对象,但是查询缓存中没有缓存某些关联对象的ID,这时个会导致重新生成SQL查询数据库。比如上面提到的Forums集合问题。二.查询缓存中有对象的ID,但是这些对象的实例却不在二级缓存中了。比如二级缓存已经失效等等,这也会导致生成SQL查询数据库。
2.对于集合字段,必须显式地使用@Cache标记,集合才会被缓存。注意,这里缓存的并不是集合的元素,而是元素的ID。集合元素能否被缓存取决于元素类有没有声明为可缓存的。 如果没有配制集合为可缓存,那么,即使在第一次查询时它们都进行入了二级缓存,下一次通过宿主类导航这个集合时还是会生成SQL,因为集合没有缓存,也就是所有元素的ID没有缓存,Hibernate不知道宿主对象关联的是那一些元素。虽然这些元素都已经在缓存中了。
从这个例子中我们可以看到:Cache的设置总是静态的全局的,不像Fetch那样可以动态重写。
django 的 prefetch()
prefetch () 类方法:
prefetch_related
, on the other hand, does a separate lookup for each relationship, and does the ''joining'' in Python. This allows it to prefetch many-to-many and many-to-one objects, which cannot be done using
For example, suppose you have these models
from django.db import models
class Topping(models.Model):
name = models.CharField(max_length=30)
class Pizza(models.Model):
name = models.CharField(max_length=50)
toppings = models.ManyToManyField(Topping)
def __str__(self):
return "%s (%s)" % (
self.name,
", ".join(topping.name for topping in self.toppings.all()),
)
and run:
class Restaurant(models.Model): pizzas = models.ManyToManyField(Pizza, related_name=''restaurants'') best_pizza = models.ForeignKey(Pizza, related_name=''championed_by'', on_delete=models.CASCADE)
>>> Pizza.objects.all() ["Hawaiian (ham, pineapple)", "Seafood (prawns, smoked salmon)"...
The problem with this is that every time Pizza.__str__()
asks for self.toppings.all()
it has to query the database, so Pizza.objects.all()
will run a query on the Toppings table for every item in the Pizza QuerySet
.
也就是说,上面的代码中每一次调用__str__(), 又要多一次查询,而不是一次 all () 查询。
prefetch () 可以只用两次查询,不是通过外键关联一次查询的方式。
>>> Pizza.objects.all().prefetch_related(''toppings'')
原理是,prefetch()将其查到的结果存到了缓存区,并做好了关联。
也可以多次连表
Restaurant.objects.prefetch_related(''pizzas__toppings'')
另外,prefetch 可以通过 Prefetch 对象,实现自定义的查询。
>>> vegetarian_pizzas = Pizza.objects.filter(vegetarian=True)
>>> Restaurant.objects.prefetch_related(
... Prefetch(''pizzas'', to_attr=''menu''),
... Prefetch(''pizzas'', queryset=vegetarian_pizzas, to_attr=''vegetarian_menu''))
需要注意的是。有一些函数会清空 prefetch()存下的数据
Remember that, as always with QuerySets
, any subsequent chained methods which imply a different database query will ignore previously cached results, and retrieve data using a fresh database query. So, if you write the following:
>>> pizzas = Pizza.objects.prefetch_related(''toppings'') >>> [list(pizza.toppings.filter(spicy=True)) for pizza in pizzas]
...then the fact that pizza.toppings.all()
has been prefetched will not help you. The prefetch_related(''toppings'')
implied pizza.toppings.all()
, but pizza.toppings.filter()
is a new and different query. The prefetched cache can''t help here; in fact it hurts performance, since you have done a database query that you haven''t used. So use this feature with caution!
Also, if you call the database-altering methods add()
, remove()
, clear()
or set()
, onrelated managers
, any prefetched cache for the relation will be cleared.
Fetch(原生)的简单使用
前言: Fetch 提供了对 Request 和 Response 等对象通用的定义。
发送请求或者获取资源,需要使用 fetch() 方法。
具体使用代码:
<script>
fetch("地址",{method:"请求方式"}).then(function (res) { //将异步数据res处理成text(转成json),
res.text().then(function (value) {
console.log(value);
})
})
</script>
示例:
get请求:
fetch("url", {
method: "get"
}).then(function(resp) {
//将服务器响应回来的内容 序列化成 json格式 使用text()也可以
resp.json().then((data) => {
// data -> 数据
})
});
post请求:
var arr1 = [{
name: "天皇盖地虎",
detail:"宝塔镇河妖"
}];
fetch("url", {
method: "post",
headers: {//设置请求的头部信息
"Content-Type": "application/json"
//跨域时可能要加上
//"Accept":"allication/json"
}, //将arr1对象序列化成json字符串
body: JSON.stringify(arr1)//向服务端传入json数据
}).then(function(resp) {
resp.json().then((data) => {
})
});
Fetch()-如何使用重定向显示位置页面:关注
如何解决Fetch()-如何使用重定向显示位置页面:关注?
问题是:
- 我通过POST发送了Fetch(),这是一个登录表单,
fetch(''/login'',{
method: ''POST'',body: _formData,credentials: ''same-origin'',redirect: ''follow''
}).then((response) => {
if (response.redirected) {
// window.location.href = response.headers.get(''Location'');
}
}).catch(function (err) {
console.info(''fetch() login issue: '' + err);
});
- 然后,服务器端以重定向响应:
HTTP/1.1 302 Found
Server: Nginx/1.16.1
Date: Fri,18 Sep 2020 09:33:33 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 10
Connection: keep-alive
Set-Cookie: _token=1050; Secure; HttpOnly
Location: /main/top
- 我所看到的-浏览器使用GET请求重定向的页面(这里是
/main/top
),并根据需要获取完整的内容HTML,我看到fiddler的流量, - 但这很非常奇怪,-浏览器获取内容,但不显示重定向页面!
- (
catch
之后fetch
中没有错误)
这可能是什么?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)
我们今天的关于多个顺序fetch和承诺的分享已经告一段落,感谢您的关注,如果您想了解更多关于Cache与Fetch(二)、django 的 prefetch()、Fetch(原生)的简单使用、Fetch()-如何使用重定向显示位置页面:关注的相关信息,请在本站查询。
本文标签: