jjzjj

javascript - Angular 两次发送 http 请求

coder 2025-02-26 原文

我用 Angular 4 编写了一个应用程序。看起来每次我尝试访问 API 时,angular 都会发出 2 个请求。我的应用程序中的所有方法都会发生这种情况,包括;获取、删除、放置、发布

我将在下面添加一些代码示例。例如,我有一个 NotificationComponent,它列出了来自数据库的所有通知。 NotificationComponent 有一个方法可以在 ngOnInit 上加载通知;

    this.NotificationService.All(AdditionalParams)
        .subscribe(
            notifications => {
              this.AllNotifications.Notifications = notifications.data;
              this.AllNotifications.Data = notifications;
              this.AllNotifications.Loading = false;
              this.AllNotifications.Loaded = true;
              this.AllNotifications.HasRequestError = false;
            },
            (error)=>  {
              this.AllNotifications.Loading = false;
              this.AllNotifications.Loaded = false;
              this.AllNotifications.RequestStatus = error.status;
              if (typeof error.json == 'function' && error.status!=0) {
                let errorObject = error.json();
                this.AllNotifications.RequestError = errorObject;
              } else {
                this.AllNotifications.RequestError = "net::ERR_CONNECTION_REFUSED";
              }
              this.AllNotifications.HasRequestError = true;
            });
  }

该方法订阅了在 NotificationService 中找到的 All 方法。 All 方法如下所示;

  All(AdditionalParams: object): Observable<any> {
    let options = new RequestOptions({ headers: this.headers });
    let params = new URLSearchParams();
    //params.set("token", this.authenticationService.token);
    for (var key in AdditionalParams) {
      params.set(key, AdditionalParams[key]);
    }
    options.params = params;
    return this.http.get(this.notificationsUrl, options)
        .map(response => response.json())
        .catch(this.handleError);
  }

不知何故请求被发送了两次。我认为这是在我的控制台日志中;

XHR finished loading: GET "[REMOVED]/notifications?page=1&event=1&token=eyJ0eXAiOi…GkiOiJ1bGYxSnJPa1Zya0M2NmxDIn0.3kA8Pd-tmOo4jUinJqcDeUy7mDPdgWpZkqd3tbs2c8A"
XHR finished loading: GET "[REMOVED]/notifications?page=1&event=1&token=eyJ0eXAiOi…GkiOiJ1bGYxSnJPa1Zya0M2NmxDIn0.3kA8Pd-tmOo4jUinJqcDeUy7mDPdgWpZkqd3tbs2c8A"

大约相隔 3 秒。

我有一个名为“AuthenticationService”的服务。在此服务中,我使用 ng-http-interceptor 添加了一个 http 拦截器。 http拦截器被添加到所有请求中。它看起来像这样;

httpInterceptor.request().addInterceptor((data, method) => {
            console.log ("Before httpInterceptor: ", data);
            var RequestOptionsIndex = null;
            for (var _i = 0; _i < data.length; _i++) {
                if (typeof data[_i] == 'object' && data[_i].hasOwnProperty('headers')){
                    RequestOptionsIndex = _i;
                }
            }
            if (RequestOptionsIndex == null) {
                let options = new RequestOptions({headers: new Headers({'Content-Type': 'application/json'})});
                let params = new URLSearchParams();
                data.push(options);
                RequestOptionsIndex = data.length-1;
            }
            //console.log (data, this.loginURL, 'RequestOptionsIndex: ', RequestOptionsIndex);
            if (!data[RequestOptionsIndex].hasOwnProperty('headers')){
                data[RequestOptionsIndex].headers = new Headers({'Content-Type': 'application/json'});
            }
            if (data[0]!=this.loginURL && (data[RequestOptionsIndex].headers.get('Authorization')=="" || data[RequestOptionsIndex].headers.get('Authorization')==null)) {
                    data[RequestOptionsIndex].headers.append("Authorization", 'Bearer ' + this.token);
            }
            if (data[RequestOptionsIndex].params!=undefined && data[RequestOptionsIndex].params!=null) {
                data[RequestOptionsIndex].params.set('token', this.token);
            }else {
                let params = new URLSearchParams();
                params.set('token', this.token);
                data[RequestOptionsIndex].params = params;
            }
            console.log ("httpInterceptor data", data, ": RequestOptionsIndex", RequestOptionsIndex);
            return data;
        });
        httpInterceptor.response().addInterceptor((res, method) => {
            res.map(response => response.json())
                .catch((err: Response, caught: Observable<any>) => {
                    if (err.status === 401) {
                        this.logout();
                        this.router.navigate(["/login"]);
                        location.reload();
                        return Observable.throw("401 Unauthorized");
                    }
                    return Observable.throw(caught); // <-----
                }).subscribe()
            return res;
        });

最佳答案

在发布问题时,我注意到我订阅了我的 httpInterceptor.response().addInterceptor 中的响应,删除 .subscribe() 修复了它。于是就变成了;

httpInterceptor.response().addInterceptor((res, method) => {
            return res.map(response => response) // => response.json()
                .catch((err: Response, caught: Observable<any>) => {
                    if (err.status === 401) {
                        this.logout();
                        this.router.navigate(["/login"]);
                        location.reload();
                        return Observable.throw("401 Unauthorized");
                    }
                    return Observable.throw(caught); // <-----
                })//.share().subscribe()
            //return res;
        });

以防万一有人犯这样的愚蠢错误。这是我的解决方案。

当您多次订阅请求时会出现问题,因此它会被执行多次。解决方案是共享请求或订阅一次。我不确定在不重新加载的情况下共享请求多个订阅的确切方法,希望有人会确认这一点。我尝试了 .share().subscribe() 但似乎对我不起作用。

关于javascript - Angular 两次发送 http 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45534491/

有关javascript - Angular 两次发送 http 请求的更多相关文章

  1. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  2. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  3. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  4. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  5. ruby - 使用 Ruby 通过 Outlook 发送消息的最简单方法是什么? - 2

    我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=

  6. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  7. ruby-on-rails - Rails - 从命名路由中提取 HTTP 动词 - 2

    Rails中有没有一种方法可以提取与路由关联的HTTP动词?例如,给定这样的路线:将“users”匹配到:“users#show”,通过:[:get,:post]我能实现这样的目标吗?users_path.respond_to?(:get)(显然#respond_to不是正确的方法)我最接近的是通过执行以下操作,但它似乎并不令人满意。Rails.application.routes.routes.named_routes["users"].constraints[:request_method]#=>/^GET$/对于上下文,我有一个设置cookie然后执行redirect_to:ba

  8. ruby-on-rails - Rake 任务仅调用一次时执行两次 - 2

    我写了一个非常简单的rake任务来尝试找到这个问题的根源。namespace:foodotaskbar::environmentdoputs'RUNNING'endend当在控制台中执行rakefoo:bar时,输出为:RUNNINGRUNNING当我执行任何rake任务时会发生这种情况。有没有人遇到过这样的事情?编辑上面的rake任务就是写在那个.rake文件中的所有内容。这是当前正在使用的Rakefile。requireFile.expand_path('../config/application',__FILE__)OurApp::Application.load_tasks这里

  9. ruby - 是否可以在不实际发送或读取数据的情况下查明 ruby​​ 套接字是否处于 ESTABLISHED 或 CLOSE_WAIT 状态? - 2

    s=Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)s.connect(Socket.pack_sockaddr_in('port','hostname'))ssl=OpenSSL::SSL::SSLSocket.new(s,sslcert)ssl.connect从这里开始,如果ssl连接和底层套接字仍然是ESTABLISHED,或者它是否在默认值7200之后进入CLOSE_WAIT,我想检查一个线程几秒钟甚至更糟的是在实际上不需要.write()或.read()的情况下关闭。是用select()、IO.select()还是其他方法完成

  10. ruby-on-rails - Heroku 吃掉了我的自定义 HTTP header - 2

    我正在使用Heroku(heroku.com)来部署我的Rails应用程序,并且正在构建一个iPhone客户端来与之交互。我的目的是将手机的唯一设备标识符作为HTTPheader传递给应用程序以进行身份​​验证。当我在本地测试时,我的header通过得很好,但在Heroku上它似乎去掉了我的自定义header。我用ruby​​脚本验证:url=URI.parse('http://#{myapp}.heroku.com/')#url=URI.parse('http://localhost:3000/')req=Net::HTTP::Post.new(url.path)#boguspara

随机推荐