久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

    1. <legend id='bhOdS'><style id='bhOdS'><dir id='bhOdS'><q id='bhOdS'></q></dir></style></legend>

        <tfoot id='bhOdS'></tfoot>

        <small id='bhOdS'></small><noframes id='bhOdS'>

        <i id='bhOdS'><tr id='bhOdS'><dt id='bhOdS'><q id='bhOdS'><span id='bhOdS'><b id='bhOdS'><form id='bhOdS'><ins id='bhOdS'></ins><ul id='bhOdS'></ul><sub id='bhOdS'></sub></form><legend id='bhOdS'></legend><bdo id='bhOdS'><pre id='bhOdS'><center id='bhOdS'></center></pre></bdo></b><th id='bhOdS'></th></span></q></dt></tr></i><div class="qwawimqqmiuu" id='bhOdS'><tfoot id='bhOdS'></tfoot><dl id='bhOdS'><fieldset id='bhOdS'></fieldset></dl></div>
          <bdo id='bhOdS'></bdo><ul id='bhOdS'></ul>

        使用 XMLHttpRequest 的內存高效消息塊處理

        Memory efficient message chunk processing using a XMLHttpRequest(使用 XMLHttpRequest 的內存高效消息塊處理)

          <bdo id='kktkf'></bdo><ul id='kktkf'></ul>
                <tbody id='kktkf'></tbody>
            • <legend id='kktkf'><style id='kktkf'><dir id='kktkf'><q id='kktkf'></q></dir></style></legend>

                <small id='kktkf'></small><noframes id='kktkf'>

                  <tfoot id='kktkf'></tfoot>
                1. <i id='kktkf'><tr id='kktkf'><dt id='kktkf'><q id='kktkf'><span id='kktkf'><b id='kktkf'><form id='kktkf'><ins id='kktkf'></ins><ul id='kktkf'></ul><sub id='kktkf'></sub></form><legend id='kktkf'></legend><bdo id='kktkf'><pre id='kktkf'><center id='kktkf'></center></pre></bdo></b><th id='kktkf'></th></span></q></dt></tr></i><div class="qwawimqqmiuu" id='kktkf'><tfoot id='kktkf'></tfoot><dl id='kktkf'><fieldset id='kktkf'></fieldset></dl></div>
                  本文介紹了使用 XMLHttpRequest 的內存高效消息塊處理的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

                  問題描述

                  我有一個 XMLHttpRequest 和一個 progress 事件處理程序,它正在請求一個連續發送添加消息塊的分塊頁面.如果我沒有設置 responseType,我可以在每個 progress 事件中訪問 XMLHttpRequestresponse 屬性,并且處理額外的消息塊.這種方法的問題是瀏覽器必須將整個響應保存在內存中,最終瀏覽器會因為這種內存浪費而崩潰.

                  I have a XMLHttpRequest with a progress event handler that is requesting a chunked page which continuously sends adds message chunks. If I do not set a responseType, I can access the response property of the XMLHttpRequest in each progress event and handle the additional message chunk. The problem of this approach is that the browser must keep the entire response in memory, and eventually, the browser will crash due to this memory waste.

                  所以,我嘗試了一個arraybufferresponseType,希望可以對緩沖區進行切片,防止之前的內存浪費過多.不幸的是,此時 progress 事件處理程序不再能夠讀取 XMLHttpRequestresponse 屬性.progress 事件的事件參數也不包含緩沖區.這是我嘗試的一個簡短的、獨立的示例(這是為 node.js 編寫的):

                  So, I tried a responseType of arraybuffer in the hope that I can slice the buffer to prevent the previous excessive memory waste. Unfortunately, the progress event handler is no longer capable of reading the response property of the XMLHttpRequest at this point. The event parameter of the progress event does not contain the buffer, either. Here is a short, self-contained example of my attempt at this (this is written for node.js):

                  var http = require('http');
                  
                  // -- The server.
                  
                  http.createServer(function(req, res) {
                    if (req.url === '/stream') return serverStream(res);
                    serverMain(res);
                  }).listen(3000);
                  
                  // -- The server functions to send a HTML page with the client code, or a stream.
                  
                  function serverMain(res) {
                    res.writeHead(200, {'Content-Type': 'text/html'});
                    res.write('<html><body>Hello World</body><script>');
                    res.end(client.toString() + ';client();</script></html>');
                  }
                  
                  function serverStream(res) {
                    res.writeHead(200, {'Content-Type': 'text/html'});
                    setInterval(function() {
                      res.write('Hello World<br />
                  ');
                    }, 1000);
                  }
                  
                  // -- The client code which runs in the browser.
                  
                  function client() {
                    var xhr = new XMLHttpRequest();
                    xhr.addEventListener('progress', function() {
                      if (!xhr.response) return console.log('progress without response :-(');
                      console.log('progress: ' + xhr.response.size);
                    }, false);
                    xhr.open('GET', '/stream', true);
                    xhr.responseType = 'arraybuffer';
                    xhr.send();
                  }
                  

                  progress 事件處理程序無法訪問我想要的 response.如何以節省內存的方式處理瀏覽器中的消息塊?請不要建議 WebSocket.我不希望只使用一個來處理消息塊的只讀流.

                  The progress event handler has no access to the response I wanted. How can I handle the message chunks in the browser in a memory-efficient way? Please do not suggest a WebSocket. I do not wish to use one just to process a read-only stream of message chunks.

                  推薦答案

                  XMLHttpRequest 似乎并不是真正為這種用法而設計的.顯而易見的解決方案是輪詢,這是 XMLHttpRequest 的一種流行用法,但我猜你不想錯過流中的數據,這些數據會在調用之間滑動.

                  XMLHttpRequest doesn't seem really designed for this kind of usage. The obvious solution is polling, which is a popular use of XMLHttpRequest but I'm guessing you don't want to miss data from your stream that would slip between the calls.

                  對于我的問題可以以某種方式識別真實"數據塊還是基本上是隨機數據?,您回答了 通過一些努力,可以通過向服務器端添加各種事件 ID 來識別塊

                  To my question Can the "real" data chunks be identified in some way or is it basically random data ?, you answered With some effort, the chunks could be identified by adding an event-id of sorts to the server-side

                  基于這個前提,我提出:

                  Based on this premise, I propose:

                  1. 連接流并設置進度監聽器(簡稱listenerA()).
                  2. 當一個塊到達時,處理它并輸出它.保留對 listenerA() 收到的第一個和最后一個塊的 id 的引用.計算 listenerA() 收到了多少塊.
                  3. listenerA() 收到一定數量的塊后,生成另一個線程"(連接 + 偵聽器,listenerB())執行步驟 1 和 2與第一個并行,但將處理后的數據保存在緩沖區中而不是輸出.
                  4. listenerA()接收到與listenerB()接收到的第一個chunk id相同的chunk時,發送一個信號給listenerB(),斷開第一個連接并終止 listenerA().
                  5. listenerB()接收到來自listenerA()的終止信號時,將緩沖區轉儲到輸出,繼續正常處理.
                  6. listenerB() 在與之前相同的條件下生成 listenerC().
                  7. 根據需要不斷重復使用盡可能多的連接和偵聽器.
                  1. Connect to the stream and set up the progress listener (referred to as listenerA()).
                  2. When a chunk arrives, process it and output it. Keep a reference to the ids of both the first and last chunk received by listenerA(). Count how many chunks listenerA() has received.
                  3. After listenerA() has received a certain amount of chunks, spawn another "thread" (connection + listener, listenerB()) doing the steps 1 and 2 in parallel to the first one but keep the processed data in a buffer instead of outputting it.
                  4. When listenerA() receives the chunk with the same id as the first chunk received by listenerB(), send a signal to listenerB(), drop the first connection and kill listenerA().
                  5. When listenerB() receives the termination signal from the listenerA(), dump the buffer to the output and keep processing normally.
                  6. Have listenerB() spawn listenerC() on the same conditions as before.
                  7. Keep repeating with as many connections + listeners as necessary.

                  通過使用兩個重疊的連接,您可以防止由于斷開單個連接然后重新連接而可能導致的塊丟失.

                  By using two overlapping connections, you can prevent the possible loss of chunks that would result from dropping a single connection and then reconnecting.

                  • 這假設所有連接的數據流都是相同的,并且不引入一些個性化設置.
                  • 根據流的輸出速率和連接延遲,從一個連接轉換到另一個連接期間的緩沖區轉儲可能會很明顯.
                  • 您還可以衡量總響應大小而不是塊數來決定何時切換到新連接.
                  • 可能需要保留一個完整的塊 id 列表以進行比較,而不僅僅是第一個和最后一個,因為我們無法保證重疊的時間.
                  • XMLHttpRequestresponseType 必須設置為其默認值"" 或"text",才能返回文本.其他數據類型不會返回部分 response.請參閱 https://xhr.spec.whatwg.org/#the-response-attribute
                  • This assumes the data stream is the same for all connections and doesn't introduce some individualized settings.
                  • Depending on the output rate of the stream and the connection delay, the buffer dump during the transition from one connection to another might be noticeable.
                  • You could also measure the total response size rather than the chunks count to decide when to switch to a new connection.
                  • It might be necessary to keep a complete list of chunks ids to compare against rather than just the first and last one because we can't guarantee the timing of the overlap.
                  • The responseType of XMLHttpRequest must be set to its default value of "" or "text", to return text. Other datatypes will not return a partial response. See https://xhr.spec.whatwg.org/#the-response-attribute

                  以下代碼是一個 node.js 服務器,它輸出一致的元素流以用于測試目的.您可以打開到它的多個連接,輸出將是相同的 accross 會話,減去可能的服務器延遲.

                  The following code is a node.js server that outputs a consistent stream of elements for testing purposes. You can open multiple connections to it, the output will be the same accross sessions, minus possible server lag.

                  http://localhost:5500/stream

                  將返回 id 為遞增數字的數據

                  will return data where id is an incremented number

                  http://localhost:5500/streamRandom

                  將返回數據,其中 id 是一個隨機的 40 個字符長的字符串.這是為了測試一個不能依賴 id 來排序數據的場景.

                  will return data where id is a random 40 characters long string. This is meant to test a scenario where the id can not be relied upon for ordering the data.

                  var crypto = require('crypto');
                  
                  // init + update nodeId
                  var nodeId     = 0;
                  var nodeIdRand = '0000000000000000000000000000000000000000';
                  
                  setInterval(function() {
                  
                      // regular id
                      ++nodeId;
                  
                      //random id
                      nodeIdRand = crypto.createHash('sha1').update(nodeId.toString()).digest('hex');
                  }, 1000);
                  
                  
                  // create server  (port 5500)
                  var http = require('http');
                  http.createServer(function(req, res) {
                  
                    if(req.url === '/stream') {
                        return serverStream(res);
                    }
                    else if(req.url === '/streamRandom') {
                        return serverStream(res, true);
                    }
                  }).listen(5500);
                  
                  
                  // serve nodeId
                  function serverStream(res, rand) {
                  
                      // headers
                      res.writeHead(200, {
                          'Content-Type'                : 'text/plain',
                          'Access-Control-Allow-Origin' : '*',
                      });
                  
                      // remember last served id
                      var last = null;
                  
                      // output interval
                      setInterval(function() {
                  
                          // output on new node
                          if(last != nodeId) {
                              res.write('[node id="'+(rand ? nodeIdRand : nodeId)+'"]');
                              last = nodeId;
                          }
                      }, 250);
                  }
                  

                  概念證明,使用上述 node.js 服務器代碼

                  <!DOCTYPE html>
                  <html>
                      <head>
                          <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
                      </head>
                      <body>
                          <button id="stop">stop</button>
                          <div id="output"></div>
                          <script>
                  
                  /*
                  Listening to a never ending page load (http stream) without running out of
                  memory by using concurrent overlapping connections to prevent loss of data,
                  using only xmlHttpRequest, under the condition that the data can be identified.
                  
                  listen arguments
                      url         url of the http stream
                      chunkMax    number of chunks to receive before switching to new connection
                  
                  listen properties
                      output           a reference to a DOM element with id "output"
                      queue            an array filled with non-duplicate received chunks and metadata
                      lastFetcherId    an incrementing number used to assign an id to new fetchers
                      fetchers         an array listing all active fetchers
                  
                  listen methods
                      fire        internal use    fire an event
                      stop        external use    stop all connections
                      fetch       internal use    starts a new connection
                      fetchRun    internal use    initialize a new fetcher object
                  
                  Usage
                  
                      var myListen = new listen('http://localhost:5500/streamRandom', 20);
                          will listen to url "http://localhost:5500/streamRandom"
                          will switch connections every 20 chunks
                  
                      myListen.stop()
                          will stop all connections in myListen
                  */
                  function listen(url, chunkMax) {
                  
                      // main ref
                      var that = this;
                  
                      // output element
                      that.output = document.getElementById('output');
                  
                      // main queue
                      that.queue = [];
                  
                      // last fetcher id
                      that.lastFetcherId = 0;
                  
                      // list of fetchers
                      that.fetchers = [];
                  
                  
                  
                  
                      //********************************************************* event dispatcher
                      that.fire = function(name, data) {
                          document.dispatchEvent(new CustomEvent(name, {'detail':data}));
                      }
                  
                  
                  
                  
                      //******************************************************** kill all fetchers
                      that.stop = function() {
                          that.fire('fetch-kill', -1);
                      }
                  
                  
                  
                  
                      //************************************************************** url fetcher
                      that.fetch = function(fetchId, url, fetchRef) {
                  
                          //console.log('start fetcher #'+fetchId);
                          var len = 0;
                          var xhr = new XMLHttpRequest();
                          var cb_progress;
                          var cb_kill;
                  
                  
                          // progress listener
                          xhr.addEventListener('progress', cb_progress = function(e) {
                  
                              // extract chunk data
                              var chunkData = xhr.response.substr(len);
                  
                              // chunk id
                              var chunkId = chunkData.match(/id="([a-z0-9]+)"/)[1];
                  
                              // update response end point
                              len = xhr.response.length;
                  
                              // signal end of chunk processing
                              that.fire('chunk-ready', {
                                  'fetchId'   : fetchId,
                                  'fetchRef'  : fetchRef,
                                  'chunkId'   : chunkId,
                                  'chunkData' : chunkData,
                              });
                          }, false);
                  
                  
                          // kill switch
                          document.addEventListener('fetch-kill', cb_kill = function(e) {
                  
                              // kill this fetcher or all fetchers (-1)
                              if(e.detail == fetchId || e.detail == -1) {
                  
                                  //console.log('kill fetcher #'+fetchId);
                  
                                  xhr.removeEventListener('progress', cb_progress);
                                  document.removeEventListener('fetch-kill', cb_kill);
                  
                                  xhr.abort();
                                  that.fetchers.shift(); // remove oldest fetcher from list
                                  xhr = null;
                                  delete xhr;
                              }
                          }, false);
                  
                  
                          // go
                          xhr.open('GET', url, true);
                          xhr.responseType = 'text';
                          xhr.send();
                      };
                  
                  
                  
                  
                      //****************************************************** start a new fetcher
                      that.fetchRun = function() {
                  
                          // new id
                          var id = ++that.lastFetcherId;
                  
                          //console.log('create fetcher #'+id);
                  
                          // create fetcher with new id
                          var fetchRef = {
                              'id'           : id,    // self id
                              'queue'        : [],    // internal queue
                              'chunksIds'    : [],    // retrieved ids, also used to count
                              'hasSuccessor' : false, // keep track of next fetcher spawn
                              'ignoreId'     : null,  // when set, ignore chunks until this id is received (this id included)
                          };
                          that.fetchers.push(fetchRef);
                  
                          // run fetcher
                          that.fetch(id, url, fetchRef);
                      };
                  
                  
                  
                  
                      //************************************************ a fetcher returns a chunk
                      document.addEventListener('chunk-ready', function(e) {
                  
                          // shorthand
                          var f = e.detail;
                  
                          // ignore flag is not set, process chunk
                          if(f.fetchRef.ignoreId == null) {
                  
                              // store chunk id
                              f.fetchRef.chunksIds.push(f.chunkId);
                  
                              // create queue item
                              var queueItem = {'id':f.chunkId, 'data':f.chunkData};
                  
                              // chunk is received from oldest fetcher
                              if(f.fetchId == that.fetchers[0].id) {
                  
                                  // send to main queue
                                  that.queue.push(queueItem);
                  
                                  // signal queue insertion
                                  that.fire('queue-new');
                              }
                              // not oldest fetcher
                              else {
                  
                                  // use fetcher internal queue
                                  f.fetchRef.queue.push(queueItem);
                              }
                          }
                          // ignore flag is set, current chunk id the one to ignore
                          else if(f.fetchRef.ignoreId == f.chunkId) {
                  
                              // disable ignore flag
                              f.fetchRef.ignoreId = null;
                          }
                  
                  
                  
                  
                  
                  
                  
                          //******************** check chunks count for fetcher, threshold reached
                          if(f.fetchRef.chunksIds.length >= chunkMax && !f.fetchRef.hasSuccessor) {
                  
                              // remember the spawn
                              f.fetchRef.hasSuccessor = true;
                  
                              // spawn new fetcher
                              that.fetchRun();
                          }
                  
                  
                  
                  
                          /***********************************************************************
                          check if the first chunk of the second oldest fetcher exists in the
                          oldest fetcher.
                          If true, then they overlap and we can kill the oldest fetcher
                          ***********************************************************************/
                          if(
                              // is this the oldest fetcher ?
                              f.fetchId == that.fetchers[0].id
                              // is there a successor ?
                              && that.fetchers[1]
                              // has oldest fetcher received the first chunk of its successor ?
                              && that.fetchers[0].chunksIds.indexOf(
                                  that.fetchers[1].chunksIds[0]
                              ) > -1
                          ) {
                  
                              // get index of last chunk of the oldest fetcher within successor queue
                              var lastChunkId    = that.fetchers[0].chunksIds[that.fetchers[0].chunksIds.length-1]
                              var lastChunkIndex = that.fetchers[1].chunksIds.indexOf(lastChunkId);
                  
                              // successor has not reached its parent last chunk
                              if(lastChunkIndex < 0) {
                  
                                  // discard whole queue
                                  that.fetchers[1].queue     = [];
                                  that.fetchers[1].chunksIds = [];
                  
                                  // set ignore id in successor to future discard duplicates
                                  that.fetchers[1].ignoreId = lastChunkId;
                              }
                              // there is overlap
                              else {
                  
                                  /**
                                  console.log('triming queue start: '+that.fetchers[1].queue.length
                                      +"   "+(lastChunkIndex+1)
                                      +"   "+(that.fetchers[1].queue.length-1)
                                  );
                                  /**/
                                  var trimStart = lastChunkIndex+1;
                                  var trimEnd   = that.fetchers[1].queue.length-1;
                  
                                  // trim queue
                                  that.fetchers[1].queue = that.fetchers[1].queue.splice(trimStart, trimEnd);
                                  that.fetchers[1].chunksIds = that.fetchers[1].chunksIds.splice(trimStart, trimEnd);
                  
                                  //console.log('triming queue end: '+that.fetchers[1].queue.length);
                              }
                  
                              // kill oldest fetcher
                              that.fire('fetch-kill', that.fetchers[0].id);
                          }
                  
                  
                  
                  
                  
                      }, false);
                  
                  
                  
                  
                      //***************************************************** main queue processor
                      document.addEventListener('queue-new', function(e) {
                  
                          // process chunks in queue
                          while(that.queue.length > 0) {
                  
                              // get chunk and remove from queue
                              var chunk = that.queue.shift();
                  
                              // output item to document
                              if(that.output) {
                                  that.output.innerHTML += "<br />"+chunk.data;
                              }
                          }
                      }, false);
                  
                  
                  
                      //****************************************************** start first fetcher
                      that.fetchRun();
                  };
                  
                  
                  // run
                  var process = new listen('http://localhost:5500/streamRandom', 20);
                  
                  // bind global kill switch to button
                  document.getElementById('stop').addEventListener('click', process.stop, false);
                  
                          </script>
                      </body>
                  </html>
                  

                  這篇關于使用 XMLHttpRequest 的內存高效消息塊處理的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

                  【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

                  相關文檔推薦

                  Browser waits for ajax call to complete even after abort has been called (jQuery)(即使在調用 abort (jQuery) 之后,瀏覽器也會等待 ajax 調用完成)
                  JavaScript innerHTML is not working for IE?(JavaScript innerHTML 不適用于 IE?)
                  XMLHttpRequest cannot load, No #39;Access-Control-Allow-Origin#39; header is present on the requested resource(XMLHttpRequest 無法加載,請求的資源上不存在“Access-Control-Allow-Origin標頭) - IT屋-程序員軟件開發技術分
                  Is it possible for XHR HEAD requests to not follow redirects (301 302)(XHR HEAD 請求是否有可能不遵循重定向 (301 302))
                  XMLHttpRequest 206 Partial Content(XMLHttpRequest 206 部分內容)
                  Restrictions of XMLHttpRequest#39;s getResponseHeader()?(XMLHttpRequest 的 getResponseHeader() 的限制?)
                    <legend id='T0hE2'><style id='T0hE2'><dir id='T0hE2'><q id='T0hE2'></q></dir></style></legend>

                    <small id='T0hE2'></small><noframes id='T0hE2'>

                          <tbody id='T0hE2'></tbody>

                      • <tfoot id='T0hE2'></tfoot>
                        <i id='T0hE2'><tr id='T0hE2'><dt id='T0hE2'><q id='T0hE2'><span id='T0hE2'><b id='T0hE2'><form id='T0hE2'><ins id='T0hE2'></ins><ul id='T0hE2'></ul><sub id='T0hE2'></sub></form><legend id='T0hE2'></legend><bdo id='T0hE2'><pre id='T0hE2'><center id='T0hE2'></center></pre></bdo></b><th id='T0hE2'></th></span></q></dt></tr></i><div class="qwawimqqmiuu" id='T0hE2'><tfoot id='T0hE2'></tfoot><dl id='T0hE2'><fieldset id='T0hE2'></fieldset></dl></div>
                          • <bdo id='T0hE2'></bdo><ul id='T0hE2'></ul>
                            主站蜘蛛池模板: 超碰97免费观看 | 福利片在线观看 | 精品久久精品 | 免费福利视频一区二区三区 | 午夜精品久久久久久久99黑人 | 国产精品美女一区二区 | 国产91色在线 | 亚洲 | 欧美激情视频一区二区三区在线播放 | 午夜免费在线 | 一级毛片视频 | 日本一区视频在线观看 | 亚洲a级| 国产精品一码二码三码在线 | www在线视频 | 仙人掌旅馆在线观看 | 亚洲av毛片 | www.4hu影院 | 日韩视频精品在线 | 成人午夜在线视频 | 久久精品色视频 | 免费在线观看黄色av | 中文字幕视频一区 | 二区国产| 91传媒在线观看 | 日韩在线大片 | 一区二区免费视频 | 欧美理论 | 久久亚洲欧美日韩精品专区 | 国产免费福利小视频 | 99久久久久久久久 | av在线视| 91在线观| 日本视频免费观看 | 欧美激情亚洲 | 视频在线一区二区 | 网站国产| 黄色免费在线观看网址 | 国产一区二区三区久久久久久久久 | 国产精品久久久久aaaa九色 | 久久久久亚洲精品 | 国产99视频精品免视看9 |