2015-01-12 64 views
4

我一直在上傳一個webworker,並發現在Chrome中工作的東西。但是,在Safari和Firefox中,我得到的FormData是未定義的。Webworker中的FormData - 在某些瀏覽器中 - 這是錯誤的嗎?

我發現這很好,並且是可以預期的:正如https://stackoverflow.com/a/13970107/1238884中所提到的,FormData沒有爲webworkers定義/支持並實現了polyfill。 (注意:更新的polyfill @https://gist.github.com/Rob--W/8b5adedd84c0d36aba64

但爲什麼它在Chrome(v39)中工作?它是否有一個錯誤的實現,或者它們是否有目的地放在那裏?

回答

0

Chrome從版本36.0.1935.0(crbug.com/360546)開始支持Web Workers中的FormData。

它的存在是因爲latest specification of FormData要求將其暴露給Worker上下文。火狐還沒有實現這一點,但它是在他們的雷達(bugzil.la/739173)。我認爲你誤讀了my answer that you've linkednew FormData(<HTMLFormElement>);不支持,因爲<form>並且基於表單元素初始化其字段的構造函數不受支持,因爲<form>元素顯然不能在Web Worker中創建。但你可以創建一個空的FormData對象,並根據需要使用它(如果瀏覽器實現了最新版本的規範)。

如果您想在所有當前瀏覽器中使用FormData API,則必須加載您在問題中引用的我的polyfill。如果檢測到FormData API已被定義,則此填充返回的時間早,因此它不會在已支持FormData的瀏覽器中引發問題。請注意,與原生FormData API相比,此polyfill的效率較低,因爲polyfill必須先在內存中創建完整字符串,而本機實現可以只保存文件的輕量級數據結構,並在從磁盤傳輸文件時文件/ Blob被上傳。

對於小的數據塊,這是一個非問題,但如果你打算上傳大文件,那麼你最好的數據使用postMessage傳遞給主線程(與transferables如果使用類型數組)和在那裏構造XMLHttpRequest對象,併發送它。 Web Workers主要用於卸載CPU繁重的任務,但XMLHttpRequest主要是網絡(發生在單獨的IO線程上,至少在Chrome中),所以在這方面沒有在主線程上使用Web Worker的好處。

+0

我的應用程序進行長時間運行(阻塞),使用相當大的斑點(幾百MEG的,通常情況下)的任務,並讓工人來執行 - 這涉及多個XHR步驟 - 它們阻止主線程拋出「等待」屏幕(我可能做錯了)。無論如何,我很高興FormData來到工人。歡呼的回覆! – frumbert

+0

>「在這方面,沒有使用網絡工作者優於主線程的好處。」也許我錯過了一些東西,但由於同步AJAX請求不再支持在主線程中,它們必須在工作線程中使用(我不認爲異步AJAX請求會在工作線程中工作(它們應該在哪裏返回數據if線程更早結束?) - 但也許我錯了)。我看不出如何按特定順序發送和接收請求。 – StanE

+0

@StanE「我認爲異步AJAX請求不會在工作線程中工作」 - 錯誤,異步請求在工作線程中完全正常工作。如果線程被終止,那麼請求可能會被取消(例如,在服務器發送請求回覆之前卸載頁面時發生的情況)。按順序發送請求是一件容易的事,只需等待請求完成(通過事件)即可。 –

1

DOM僅在單線程瀏覽器的土地一側發揮出色 - 爲此Web Worker有意沒有直接(可寫)訪問DOM ......當然,您可以隨意postMessage在地址空間中複製值

0

FormData並未在某些瀏覽器上定義,但File也是如此。這裏FORMDATA代碼不使用File對象:

/* 
* FormData for XMLHttpRequest 2 - Polyfill for Web Worker (c) 2012 Rob W 
* License: Creative Commons BY - http://creativecommons.org/licenses/by/3.0/ 
* - append(name, value[, filename]) 
* - toString: Returns an ArrayBuffer object 
* 
* Specification: http://www.w3.org/TR/XMLHttpRequest/#formdata 
*    http://www.w3.org/TR/XMLHttpRequest/#the-send-method 
* The .append() implementation also accepts Uint8Array and ArrayBuffer objects 
* Web Workers do not natively support FormData: 
*    http://dev.w3.org/html5/workers/#apis-available-to-workers 
**/ 
(function() { 
    // Export variable to the global scope 
    (this == undefined ? self : this)['FormData'] = FormData; 

    var ___send$rw = XMLHttpRequest.prototype.send; 
    XMLHttpRequest.prototype['send'] = function(data) { 
     if (data instanceof FormData) { 
      if (!data.__endedMultipart) data.__append('--' + data.boundary + '--\r\n'); 
      data.__endedMultipart = true; 
      this.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + data.boundary); 
      data = new Uint8Array(data.data).buffer; 
     } 
     // Invoke original XHR.send 
     return ___send$rw.call(this, data); 
    }; 

    function FormData() { 
     // Force a Constructor 
     if (!(this instanceof FormData)) return new FormData(); 
     // Generate a random boundary - This must be unique with respect to the form's contents. 
     this.boundary = '------RWWorkerFormDataBoundary' + Math.random().toString(36); 
     var internal_data = this.data = []; 
     /** 
     * Internal method. 
     * @param inp String | ArrayBuffer | Uint8Array Input 
     */ 
     this.__append = function(inp) { 
      var i=0, len; 
      if (typeof inp === 'string') { 
       for (len=inp.length; i<len; i++) 
        internal_data.push(inp.charCodeAt(i) & 0xff); 
      } else if (inp && inp.byteLength) {/*If ArrayBuffer or typed array */ 
       if (!('byteOffset' in inp)) /* If ArrayBuffer, wrap in view */ 
        inp = new Uint8Array(inp); 
       for (len=inp.byteLength; i<len; i++) 
        internal_data.push(inp[i] & 0xff); 
      } 
     }; 
    } 
    /** 
    * @param name  String         Key name 
    * @param value String|Blob|File|Uint8Array|ArrayBuffer Value 
    * @param filename String         Optional File name (when value is not a string). 
    **/ 
    FormData.prototype['append'] = function(name, value, filename) { 
     if (this.__endedMultipart) { 
      // Truncate the closing boundary 
      this.data.length -= this.boundary.length + 6; 
      this.__endedMultipart = false; 
     } 
     var valueType = Object.prototype.toString.call(value), 
      part = '--' + this.boundary + '\r\n' + 
       'Content-Disposition: form-data; name="' + name + '"'; 

     if (/^\[object (?:Blob|File)(?:Constructor)?\]$/.test(valueType)) { 
      return this.append(name, 
          new Uint8Array(new FileReaderSync().readAsArrayBuffer(value)), 
          filename || value.name); 
     } else if (/^\[object (?:Uint8Array|ArrayBuffer)(?:Constructor)?\]$/.test(valueType)) { 
      part += '; filename="'+ (filename || 'blob').replace(/"/g,'%22') +'"\r\n'; 
      part += 'Content-Type: application/octet-stream\r\n\r\n'; 
      this.__append(part); 
      this.__append(value); 
      part = '\r\n'; 
     } else { 
      part += '\r\n\r\n' + value + '\r\n'; 
     } 
     this.__append(part); 
    }; 
})(); 
相關問題