众所周知,React Native (以下简称RN)中缺乏很多标准的浏览器API,而这让我在尝试使用XMPP协议开发IM应用的时候遭遇到了麻烦
在浏览器中使用XMPP的时候,一般来说会搭配strophe.js来使用,然而在RN中使用strophe会报错,因为strophe中有大量类似
xmlHtmlNode: function (html)
{
var node;
//ensure text is escaped
if (window.DOMParser) {
var parser = new DOMParser();
node = parser.parseFromString(html, "text/xml");
} else {
node = new ActiveXObject("Microsoft.XMLDOM");
node.async="false";
node.loadXML(html);
}
return node;
},
这样的使用,也就是说,需要一个DOMParser来解析接收和发送出去的XML消息体,而在RN环境下,是没有这个DOMParser的,所以我们需要手动模拟一个
首先引入xmldom依赖
npm install xmldom --save
or
yarn add xmldom
然后创建一个一个类似browser-polyfills.js
内容如下
import { DOMParser } from 'xmldom';
;(global => {
if (typeof global.document === 'undefined') {
const document = new DOMParser().parseFromString(
'<html><head></head><body></body></html>',
'text/xml')
global.document = document
global.DOMParser = DOMParser
}
})(global || window || this)
但是,这还没有完,如果你的XMPP连接是通过类似
const connection = new Strophe.Connection('http://example.com')
的方式创建的,也就是BOSH,那么你依然没办法正常收发XMPP消息体,因为RN模拟的XMLHttpRequest和标准浏览器的并不一样!
修改brower-polyfills.js
import { DOMParser } from 'xmldom'
;(global => {
if (typeof global.document === 'undefined') {
const document = new DOMParser().parseFromString(
'<html><head></head><body></body></html>',
'text/xml')
global.document = document
global.DOMParser = DOMParser
}
// XMLHttpRequest
if (global.XMLHttpRequest) {
const { prototype } = global.XMLHttpRequest
// XMLHttpRequest.responseXML
// Required by:
// - Strophe
if (prototype && !prototype.hasOwnProperty('responseXML')) {
Object.defineProperty(prototype, 'responseXML', {
get() {
const { responseText } = this
return (
responseText
&& new DOMParser().parseFromString(
responseText,
'text/xml'))
}
})
}
}
})(global || window || this)
然后,在你希望的地方引入这个文件
import './broswer-polyfills'
以上,希望对你有所帮助
网友评论