在IOS wkwebview JavaScript桥中重写open(),send()和相关的XMLHttpRequest方法。能成功完成吗?

时间:2018-10-23 12:32:39

标签: javascript ios swift wkwebview

这个想法是在将包含潜在复杂JavaScript和HTML的Web视图加载到WKWebView之前,将IOS本机代码加载到javascript桥文件中。此javascript桥将覆盖XMLHttpRequst对象上的open(),send(),fetch()和相关方法,以通过IOS本机代码而不是直接通过XHR路由所有Http通信。如果请求是异步的,则当准备好返回响应时,将创建一个Promise并由IOS本机代码调用resolvePromise()。

XMLHttpRequest.prototype.send =  function(data) {
console.log("Overriden ajax ::XMLHttpRequest.prototype.send:", arguments);
console.log('uri',this.uri);
    console.log("xhrObj::", this);
    if(!this.uri) {
        return this.realSend.apply(this, arguments);
    }

// generate a unique id to reference the promise later from native function
var promiseId = generateUUID();

updateReadyState(this, 2);

delegateHttpToNativeWithPromise(promiseId, this, this.uri, this.httpMethod, data)
.then(function(responseWrapper) {
      console.log('send resolve() - promise returned with responseWrapper',  responseWrapper);

      updateReadyState(responseWrapper.xhrObj, 3)
      updateReadyState(responseWrapper.xhrObj, 4)

      return responseWrapper.response;
      }, function(xhrObj) {
      console.log('send reject() - promise errorred with responseWrapper', responseWrapper);
      updateReadyState(responseWrapper.xhrObj, 3)
      updateReadyState(responseWrapper.xhrObj, 4)

      return responseWrapper.response;

      });

}

function delegateHttpToNativeWithPromise(promiseId, xhrObject, relativeIBAuthUri, methodType, payload) {
var promise = new Promise(function(resolve, reject) {
          methodType = methodType || "get";

          // save reference to promise in the global variable
          promises[promiseId] = { resolve, reject, xhrObject };

          try {
            // call native function
            if(window.webkit) {
                window.webkit.messageHandlers.nativeNetwork.postMessage({
                        promiseId: promiseId,
                        apiUri: relativeIBAuthUri,
                        methodType: methodType,
                        requestHeaders : requestHeaders,
                        payload: payload});
            } 
            requestHeaders = [];
          }
          catch(exception) {
            console.error(exception)
            // handle it somehow
          }
});
return promise;

}

function resolvePromise(promiseId, status, headers, encodedResponse, error) {
var response = atob(encodedResponse);
if(promises[promiseId]) {
    var xhrObj = promises[promiseId].xhrObject || null;
    if(xhrObj != null) {
        setReadOnlyProperty(xhrObj, "response", response);
        setReadOnlyProperty(xhrObj, "responseText", response);
        setReadOnlyProperty(xhrObj, "status", status);
        setReadOnlyProperty(xhrObj, "statusText", "OK");
        setReadOnlyProperty(xhrObj, "responseHeaders",headers);
    }
    if (error){
        console.log('resolvePromise - error', error);
        promises[promiseId].reject({response: response, xhrObj:xhrObj});
    } else{
        console.log('resolvePromise - success, resolving...');
        promises[promiseId].resolve({response: response, xhrObj:xhrObj});
    }
    // remove reference to stored promise
    delete promises[promiseId];
}
else {
    console.log('promiseId not found in ', promises);
}

}

XMLHttpRequest.prototype.getResponseHeader = function(header) {
console.log('getResponseHeader', this);
if(!this.responseHeaders || this.responseHeaders == null) {
    return null;
}
return this.responseHeaders[header];

}

XMLHttpRequest.prototype.getAllResponseHeaders = function() {
if(!this.responseHeaders || this.responseHeaders == null) {
    return "";
}
var response = "";
for(header in this.responseHeaders) {
    response += header+": "+this.responseHeaders[header]+"\r\n";
}
console.log('getAllResponseHeaders',response);
return response;

}

是否可以成功覆盖所有这些方法?我的最初发现表明不可以,因为原生XHR方法的复杂性无法用Javascript复制。

0 个答案:

没有答案