Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/467.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript ajax请求期间未触发websocket onmessage_Javascript_Perl_Mojolicious - Fatal编程技术网

Javascript ajax请求期间未触发websocket onmessage

Javascript ajax请求期间未触发websocket onmessage,javascript,perl,mojolicious,Javascript,Perl,Mojolicious,我有一个执行Jquery.post数据库查询请求的web应用程序。我还有三个不同的web套接字连接,用于将状态更新从服务器推送到客户端(实时图表中的CPU和内存统计、数据库状态和查询队列)。当查询没有运行时,一切都会顺利进行,但是一旦查询启动(post请求),那么三个web套接字连接似乎会在等待查询返回时挂起/阻塞。我读过这篇文章,但没有找到任何相关的答案……我怀疑这可能是我自己的愚蠢行为……但这让我在一天中的大部分时间里都在挠头。我想我可能会尝试将web套接字连接移动到web workers…

我有一个执行Jquery.post数据库查询请求的web应用程序。我还有三个不同的web套接字连接,用于将状态更新从服务器推送到客户端(实时图表中的CPU和内存统计、数据库状态和查询队列)。当查询没有运行时,一切都会顺利进行,但是一旦查询启动(post请求),那么三个web套接字连接似乎会在等待查询返回时挂起/阻塞。我读过这篇文章,但没有找到任何相关的答案……我怀疑这可能是我自己的愚蠢行为……但这让我在一天中的大部分时间里都在挠头。我想我可能会尝试将web套接字连接移动到web workers…但从理论上讲,帖子一开始就不应该被阻止…因此,这里是相关的代码片段…完整的源代码是几千行代码…因此我不想让任何人被它淹没…但如果它有用,我可以展示它。所以,最大的问题是我做错了什么?或者,我是否误解了AJAX调用在阻塞方面的工作方式

    // query execution button that grabs the query for the most recently focused query source (SPARQL editor, history, or canned)
      $("#querySubmitButton").on("click", function(e) {
        // Disable the query button
        $("#querySubmitButton").attr('disabled',true);

        // Let's make sure we are clearing out the work area and the popup contents
        $("#viz").empty();

        // Get YASQE to tell us what type of query we are running
        var queryType = editor.getQueryType();

        // refactored so that we can clean up the on-click function and also make other query types in a more modular way
        switch(queryType) {
          case 'SELECT':
            sparqlSelect();
            break;
          case 'CONSTRUCT':
            sparqlConstruct();
            break;
          case 'ASK':
            sparqlAsk();
            break;
          case 'DESCRIBE':
            sparqlDescribe();
            break;
          case 'INSERT':
            sparqlInsert();
            break;
          default:
            popup.show("Unrecognized query type.","error");
            break;
        }
      });

// Functions to do each of the query types (SELECT, CONSTRUCT, ASK, DESCRIBE, INSERT)
  // SELECT
  function sparqlSelect() {
    $.post("sparqlSelect", { database: $("#DB_label").html(),'query': editor.getValue() }).done(function(data, textStatus, xhr) {
      // Enable the query button
      $("#querySubmitButton").removeAttr('disabled');

      // If the query worked, store it
      storeQueryHistory(query);

      // if the previous query was a CONSTRUCT, then lets hide the graph metrics button
      $("#nav-trigger-graphStatistics").fadeOut(800);

      // Need to slide the query menu back
      sliders("in",$("#nav-trigger-query").attr("id"));

      var columns = [];
      var fields = [];
      var comboboxFields = [];


      // Hide the graph search panel
      $("#graphSearch").fadeOut(1400);

      // Show the results and visualization button/tab
      $("#nav-trigger-results").fadeIn(1400);
      $("#nav-trigger-visualization").fadeIn(1400);


      $.each(data.results.head.vars, function(index, value) {
        columns.push({'field': value, 'title': value});
        var to = {};
        to[value] = {type: "string"};
        fields.push(to);

        // Let's also populate the two Comboboxes for the Visualization while we are at it
        comboboxFields.push({'text': value, 'value': value});
      });

      // Now, set the two combobox datasources for visualizations
      var categoriesDS = new kendo.data.DataSource({
          data: comboboxFields
      });
      vizCategoryAxis.setDataSource(categoriesDS);

      var valuesDS = new kendo.data.DataSource({
          data: comboboxFields
      });
      vizValueAxis.setDataSource(valuesDS);

      var dataBindings = [];
      $.each(data.results.results.bindings, function(index1, value) {
        var tempobj = {};
        $.each(value, function(k1,v1) {
          tempobj[k1] = v1.value;
        });
        tempobj.id=index1;
        dataBindings.push(tempobj);
      });

      var configuration = {
        dataSource: {
          data: dataBindings,
          pageSize: 25
        },
        height: 400,
        scrollable: true,
        sortable: true,
        filterable: true,
        reorderable: true,
        resizable: true,
        toolbar: ["excel"],
        excel: {
          allPages: true,
          filterable: true,
          proxyURL: "/saveExcel"
        },
        pageable: {
          input: true,
          numeric: false,
          pageSizes: true
        },
        'columns': columns,
        dataBound: function(e) {
          $(e.sender.element).find('td').each(function() {
            var temp = $(this).html();
            if (isUrl(temp)) {
              $(this).html('<a href="' + temp + '" target="_blank">' + temp + '</a>');
            }
          });
        }
      };

      // Create the popup window
      var gridWindow = $("#resultsPopup").kendoWindow({
        width: "70%",
        title: "Query Results",
        actions: [
            "Minimize",
            "Maximize",
            "Close"
        ]
      }).data('kendoWindow');

      // Center and show the popup window
      gridWindow.center().open();

      // Create/update/refresh the grid
      resultsGrid.setOptions(configuration);
      resultsGrid.dataSource.page(1);

      $("#nav-trigger-results").on('click',function() {
        // Center and show the popup window
        gridWindow.center().open();
      });
    }).fail(function(xhr) {
      // If we are timed-out
      if (xhr.status === 401) {
        // First, clear the host, database, and status text
        $("#host_label").html('');
        $("#DB_label").html('');
        $("#status_label").html('');

        // Next, disable the query button
        $("#querySubmitButton").attr('disabled',true);

        // Change "login" tab text color to red so we know we are no longer logged in
        var styles = { 'color': "#FFCCD2" };
        $("#nav-trigger-login").css(styles);

        popup.show("Session for " + host + " has timed out, please log back in.","error");
      }
      else {
        // Enable the query button
        $("#querySubmitButton").removeAttr('disabled');
        popup.show("Error, no results (" + xhr.status + " " + xhr.statusText + ")","error");
      }
    });
  }

  // Function to connect to the query queue websocket
  function queueWebsocketConnect() {
    var qws = new WebSocket('wss://endeavour:3000/queue');

    // Let's disconnect our Websocket connections when we leave the app
    $(window).on('unload', function() {
      console.log('Websocket connection closed');
      qws.close();
    });

    // Status websocket onopen
    qws.onopen = function () {
      console.log('Websocket connection opened');
      popup.show("Websocket connection opened","success");
    };

    qws.onclose = function (event) {
      console.log('Websocket connection closed');
      popup.show("Websocket connection closed","info");
    };

    qws.onmessage = function (msg) {
      var res = JSON.parse(msg.data);
      var tableRows = '<thead><tr><td>Query Position</td><td>Query ID</td><td>Kill/Cancel Query</td></tr></thead><tbody>';
      if (res.executing != null && res.entry.length > 0) {
        $("#queryQueue").empty();
        tableRows += '<tr><td>1</td><td>' + res.executing.id + '</td><td><input type="button" class="k-button" value="Kill"></td></tr>';

        $.each(res.entry, function(index,object) {
          tableRows += '<tr><td>' + (object.pos + 1) + '</td><td>' + object.query.id + '</td><td><input type="button" class="k-button" value="Cancel"></td></tr>';
        });
        tableRows += '</tbody>';
        $("#queryQueue").html(tableRows);
      }
      else if (res.executing != null) {
        $("#queryQueue").empty();
        tableRows += '<tr><td>1</td><td>' + res.executing.id + '</td><td><input type="button" class="k-button" value="Kill"></td></tr>';
        tableRows += '</tbody>';
        $("#queryQueue").html(tableRows);
      }
      else {
        console.log(res);
        $("#queryQueue").empty();
      }
    };
  }

  // Function to connect to the stats websocket
  function websocketConnect () {
    // Set up websocket connection for system stats
    var ws = new WebSocket('wss://endeavour:3000/stats');

    // Let's disconnect our Websocket connections when we leave the app
    $(window).on('unload', function() {
      console.log('Websocket connection closed');
      ws.close();
    });

    // Status websocket onopen
    ws.onopen = function () {
      console.log('Websocket connection opened');
      popup.show("Websocket connection opened","success");
    };

    // Status websocket onclose
    ws.onclose = function (event) {
      // Disable the query button
        $("#querySubmitButton").attr('disabled',true);

      // Change "login" tab text color to red so we know we are no longer logged in
      var styles = { 'color': "#FFCCD2" };
      $("#nav-trigger-login").css(styles);

      // Clear the host, database, and status text
      $("#host_label").html('');
      $("#DB_label").html('');
      $("#status_label").html('');
      console.log('Websocket connection closed');
      popup.show("Websocket connection closed","error");

      $("#websocketReconnectButtonYes").on('click', function() {
        websocketConnect();
        queueWebsocketConnect();
        websocketReconnect.close();
      });

      $("#websocketReconnectButtonNo").on('click', function() {
        websocketReconnect.close();
      });

      websocketReconnect.center().open();
    };

    // When updates are received, push them out to update the details
    var logoutCount = 0;
    ws.onmessage = function (msg) {
      if (msg.data === 'loggedOut') {
        // Ensure we only emit this one time instead of a stream of them
        if (logoutCount == 0) {
          // Disable the query button
          $("#querySubmitButton").attr('disabled',true);

          // Change "login" tab text color to red so we know we are no longer logged in
          var styles = { 'color': "#FFCCD2" };
          $("#nav-trigger-login").css(styles);

          // Clear the host, database, and status text
          $("#host_label").html('');
          $("#DB_label").html('');
          $("#status_label").html('');

          console.log("Session for " + $("#host_label").html() + " has timed out, please log back in.");
          popup.show("Session for " + $("#host_label").html() + " has timed out, please log back in.","error");
        }
        logoutCount = 1;
      }
      else {
        logoutCount = 0;
        var res = JSON.parse(msg.data);
        var host = $("#host_label").html();
        var pdatabase = $("#DB_label").html();
        var pstatus = $("#status_label").html();

        // Disable the query button unless the database is "CONNECTED"
        if ($("#status_label").html() !== res.current.databaseStatus) {
          if (res.current.databaseStatus !== "CONNECTED") {
            $("#querySubmitButton").attr('disabled',true);
          }
          else {
            $("#querySubmitButton").removeAttr('disabled');
          }

          if (res.current.databaseStatus == 'CONNECTED' || res.current.databaseStatus == 'STOPPED') {
            $("#startDB").removeAttr('disabled');
          }
          else {
            $("#startDB").attr('disabled',true);
          }
        }

        // Maybe a more intelligent way to do this, but need to make sure that if the cookie is still valid, then populate the database login stuff
        if ($("#dbConfigHost").val() == "" && $("#dbConfigUser").val() == "") {
          $("#dbConfigHost").val(res.host);
          $("#dbConfigUser").val(res.user);

          // Change "login" tab text color to green so we know we are logged in
          var styles = { 'color': "#C5E6CC" };
          $("#nav-trigger-login").css(styles);

          var databasesDS = new kendo.data.DataSource({
            data: res.databases.database
          });
          databasePicker.setDataSource(databasesDS);
        }

        // Update the labels when values change
        if (res.host != $("#host_label").html()) {
          $("#host_label").html(res.host);
          popup.show("Host changed to " + res.host,"info");
        }
        if (pdatabase != res.current.name) {
          $("#DB_label").html(res.current.name);
          popup.show("Database changed to " + res.current.name ,"info");
        }
        if (pstatus != res.current.databaseStatus) {
          $("#status_label").html(res.current.databaseStatus);
        }

        // Update the sparklines
        cpulog.options.series[0].data = res.system.cpu;
        cpulog.refresh();
        memlog.options.series[0].data = res.system.mem;
        memlog.refresh();
      }
    };

    // Open the websocket connection to listen for changes to the query list
    var queryWS = new WebSocket('wss://endeavour:3000/queryList');

    queryWS.onmessage = function(msg) {
      var res = JSON.parse(msg.data);
      var queriesDS = new kendo.data.DataSource({
          data: res
      });
      cannedQuery.setDataSource(queriesDS);
    };
  }
//获取最近关注的查询源(SPARQL编辑器、历史记录或目录)的查询的查询执行按钮
$(“#查询SubmitButton”)。在(“单击”上,函数(e){
//禁用查询按钮
$(“#querySubmitButton”).attr('disabled',true);
//让我们确保清除工作区和弹出内容
$(“#viz”).empty();
//让YASQE告诉我们正在运行什么类型的查询
var queryType=editor.getQueryType();
//进行了重构,以便我们可以清理on-click函数,并以更模块化的方式创建其他查询类型
开关(查询类型){
案例“选择”:
sparqlSelect();
打破
案例“构造”:
sparqlConstruct();
打破
案例“询问”:
sparqlAsk();
打破
案例“描述”:
sparqlldescripe();
打破
案例“插入”:
sparqlsert();
打破
违约:
show(“无法识别的查询类型”,“错误”);
打破
}
});
//执行每种查询类型(选择、构造、询问、描述、插入)的函数
//挑选
函数sparqlSelect(){
$.post(“sparqlSelect”,{database:$(“#DB_label”).html(),'query':editor.getValue()}).done(函数(数据、文本状态、xhr){
//启用查询按钮
$(“#querySubmitButton”).removeAttr('disabled');
//如果查询有效,则存储它
storeQueryHistory(查询);
//如果前面的查询是一个构造,那么让我们隐藏graph metrics按钮
美元(“#导航触发图统计”)。淡出(800);
//需要向后滑动查询菜单
滑块(“in”,$(“导航触发器查询”).attr(“id”);
var列=[];
var字段=[];
var comboboxFields=[];
//隐藏图形搜索面板
美元(“#图形搜索”)。淡出(1400);
//显示结果和可视化按钮/选项卡
美元(“#导航触发结果”)。fadeIn(1400);
美元(“#导航触发可视化”)。fadeIn(1400);
$.each(data.results.head.vars,函数(索引,值){
push({'field':value,'title':value});
var to={};
to[value]={type:“string”};
字段。推(到);
//在进行可视化时,让我们也填充两个组合框
push({'text':value,'value':value});
});
//现在,为可视化设置两个combobox数据源
var categoriesDS=new kendo.data.DataSource({
数据:comboboxFields
});
vizCategoryAxis.setDataSource(categoriesDS);
var valuesDS=新的kendo.data.DataSource({
数据:comboboxFields
});
vizValueAxis.setDataSource(valuesDS);
var数据绑定=[];
$.each(data.results.results.bindings,函数(index1,value){
var tempobj={};
$.each(值、函数(k1、v1){
tempobj[k1]=v1.0值;
});
tempobj.id=index1;
数据绑定推送(tempobj);
});
变量配置={
数据源:{
数据:数据绑定,
页面大小:25
},
身高:400,
可滚动:对,
可排序:是的,
可过滤:正确,
可重定额:对,
可调整大小:正确,
工具栏:[“excel”],
卓越:{
是的,
可过滤:正确,
proxyURL:“/saveExcel”
},
可分页:{
输入:正确,
数字:false,
页面大小:正确
},
“列”:列,
数据绑定:函数(e){
$(e.sender.element).find('td').each(function(){
var temp=$(this.html();
if(isUrl(temp)){
$(this.html(“”);
}
});
}
};
//创建弹出窗口
var gridWindow=$(“#结果弹出”).kendoWindow({
宽度:“70%”,
标题:“查询结果”,
行动:[
“最小化”,
“最大化”,
“结束”
]
}).数据(“kendoWindow”);
//居中并显示弹出窗口
gridWindow.center().open();
//创建/更新/刷新网格
resultsGrid.setOptions(配置);
resultsGrid.dataSource.page(1);
$(“#导航触发结果”)。在('单击',函数()上{
//居中并显示弹出窗口
gridWindow.center().open();
});
}).失败(功能(xhr){
//如果我们超时了
如果(xhr.status==401){
//首先,清除主机、数据库和状态文本
$(“#主机标签”).html(“”);
$(“#DB_标签”).html(“”);
$(“#状态标签”).html(“”);
//接下来,禁用查询按钮
$(“#querySubmi
my $tx = $ua->get('http://foo.bar?query=getSomeFoo');
if($tx->success) {
    $self->render($tx->res->content);
}
else {
    $self->rendered($tx->res->code);
}
$ua->get('http://foo.bar?query=getSomeFoo' => sub {
    my ($ua,$tx) = @_;
    if($tx->success) {
        $self->render($tx->res->content);
    }
    else {
        $self->rendered($tx->res->code);
    }
});