GVKun编程网logo

多个顺序fetch()承诺(fetch顺序无效)

17

在本文中,我们将为您详细介绍多个顺序fetch的相关知识,并且为您解答关于承诺的疑问,此外,我们还会提供一些关于Cache与Fetch(二)、django的prefetch()、Fetch(原生)的简

在本文中,我们将为您详细介绍多个顺序fetch的相关知识,并且为您解答关于承诺的疑问,此外,我们还会提供一些关于Cache与Fetch(二)、django 的 prefetch()、Fetch(原生)的简单使用、Fetch()-如何使用重定向显示位置页面:关注的有用信息。

本文目录一览:

多个顺序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(二)

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()

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(原生)的简单使用

前言: 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()-如何使用重定向显示位置页面:关注

如何解决Fetch()-如何使用重定向显示位置页面:关注?

问题是:

  1. 我通过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);
        });
  1. 然后,服务器端以重定向响应:
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
  1. 我所看到的-浏览器使用GET请求重定向的页面(这里是/main/top),并根据需要获取完整的内容HTML,我看到fiddler的流量,
  2. 但这很非常奇怪,-浏览器获取内容,但不显示重定向页面!
  3. catch之后fetch中没有错误)

这可能是什么?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

我们今天的关于多个顺序fetch承诺的分享已经告一段落,感谢您的关注,如果您想了解更多关于Cache与Fetch(二)、django 的 prefetch()、Fetch(原生)的简单使用、Fetch()-如何使用重定向显示位置页面:关注的相关信息,请在本站查询。

本文标签: