服务器如何调用客户端页面上的JS

JavaScript016

服务器如何调用客户端页面上的JS,第1张

一般是这样的:在客户端启动的时候,保持一个跟服务器的长链接(使用http 1.1协议,通过设置keep-alive属性来保证链接持续时间很长),然后客户端另开一个线程监听这个链接,然后服务器可以通过这个连接来发送相应的指令(自己定义的指令),客户端接收到之后,对这个指令进行解析和执行操作。(比如服务器发一个"getDeviceStatus"的字符串过去,然后客户端解析到该字符串后,调用相应的getDeviceStatus的方法),关于长连接的详细,google一下就知道了。

如果你指的客户端是浏览器的话,那就只能是浏览器主动调服务器的接口才行。

JsLoader,动态加载远程js代码

/**

* Construct a new JSLoaderEnvironment instance

* @class JSLoaderEnvironment is the class designed to be a

* representation of a unix-like shell environment.

* The purpose of this is to allow the infrastructure to abstract

* away any library file location knowledge for rapid and enterprise

* adoption and deployment

*/

function JSLoaderEnvironment(){

// Default

this.prefix="/assets/"

// Auto-discover location

var _remote=false

var s=0

var _script_tags=document.getElementsByTagName("script")

var endsWith=function(str, substr){

return (str &&str.indexOf(substr) == (str.length-substr.length))

}

for(s=0s<_script_tags.length++s){

var src=_script_tags[s].src

var src_orig=src

if(src){

if(src.indexOf("://")>-1)

{

src=src.substring(src.indexOf("://")+3)

src=src.substring(src.indexOf("/"))

}

if(endsWith(src,"jsloader.js") || endsWith(src,"jsloader-debug.js")) {

// If the domain is remote, assume we're running in hosted mode

_remote=(src_orig.indexOf(document.domain)==-1)

if(_remote) src=src_orig

this.prefix=src.substring(0, src.lastIndexOf("/")+1)

}

}

}

/**

* @private

*/

this.suffix=".js"

/**

* @private

* Make the Path of a module to meta/proj/release

*/

this.makeJSLoaderPath=function(m,p,r,suff){

// if just a url is specified, use it

if(!p &&!r) return this.stripExternalRef(m)

// build the m/p/r path

return this.prefix+m+"/"+p+"/incr/versions/"+r+ ((suff)?this.suffix:"")

}

/**

* The generate the path prefix for a MPR linked into the JSLoader Environmentiables

* @param m meta

* @param p project

* @param r release

*/

this.makePath=function(m,p,r){

// if just a url is specified, use it

if(!p &&!r) return this.stripExternalRef(m)

// build the m/p/r path

return this.prefix + m +"/" + p + "/" + r + "/"

}

/**

* @private

*/

this.env=new Object()

/**

* @private

*/

this.loaders=new Object()

/**

* The sets an environment variable (make sure it's safe for JS Object[key] notation)

* The idea here is that modules could set this, and pages which load the module

* can then get the Environment variables

* @param k javascript object[key]

* @param v value (technically could be of any type...)

*/

this.setEnv=function(k,v){

this.env[k]=v

}

/**

* The gets an environment variable previously set

* @param k javascript object[key]

* @returns the value set for this key

*/

this.getEnv=function(k){ return this.env[k]}

/**

* Lists all modules

* loaded in this environment.

* @private

*/

this._loadedJSLoaders=new Object()

/**

* This makes a normalized key to stick into loaded_modules and verify if things are loaded.

* @private

*/

this.normalize=function(m,p,r){ return (m+"__"+p+"__"+r).toLowerCase()}

/**

* This checks whether the given meta/project/release is already loaded.

* @param m metaproject (or the path of a JS file, if no other args are passed)

* @param p project

* @param r release

* @type boolean

* @returns Whether m/p/r is loaded

*/

this.isLoaded=function(m,p,r){

var xkey=this.normalize(m,p,r)

return(this._loadedJSLoaders[xkey]!=null)

}

/**

* Gets a "loader" based on the MPR specified in the arguments

* This is useful for loading subpackages. You can call {@link JSSubLoader#load} or {@link JSSubLoader#loadAll} on this

* and it will load submodules under a folder with the "release" number

* @see JSSubLoader

* @param m metaproject

* @param p project

* @param r release

* @returns void

*/

this.getLoader=function(m,p,r){

var key=this.normalize(m,p,r)

var loader=this.loaders[key]

if(loader) {

return loader

}

else {

loader=new JSSubLoader(this,this.makeJSLoaderPath(m,p,r,false)+"/")

var __path=this.makePath(m,p,r)

this.setEnv(p.toUpperCase()+"_PATH",__path)

this.loaders[key]=loader

return loader

}

}

/**

* Loads the requested module into the environment

* You can also load your own module by calling loadJavascript(url) if you want

* @param m metaproject

* @param p project

* @param r release

* @type boolean

* @returns void

*/

this.load=function(m,p,r){

var key=this.normalize(m,p,r)

var url=this.makeJSLoaderPath(m,p,r,true)

try{

if(this.isLoaded(m,p,r)) {

return

}

this.loadJavaScript(url)

this._loadedJSLoaders[key]="true"

} catch (e){ this.handleError(e)}

}

/**

* Loads a JavaScript file into the page

* @param {String} url the url of the javascript file

*/

this.loadJavaScript=function (url){

url = this.stripExternalRef(url)

document.writeln("<scri"+"pt src='"+url+"' type='text/javascript'></sc"+"ript>")

}

/**

* Loads a JavaScript file into the page

* @param {String} url the url of the javascript file

*/

this.loadStyleSheet=function(url){

url = this.stripExternalRef(url)

document.writeln("<li"+"nk rel='stylesheet' href='"+url+"' type='text/css'></li"+"nk>")

}

/**

* Strips out any double slashes, double dots, or cross domain references.

* @param s string

*/

this.stripExternalRef=function(s){

var exprs = [/\.\.+/g,/\/\/+/g,/\\\\+/g,/\:+/g,/\'+/g,/\%+/g]

// If it's hosted, we relax the protocol related regex

exprs = [/\.\.+/g,/\\\\+/g,/\'+/g,/\%+/g]

if (_remote)

for(var i=0i<exprs.lengthi++)

{

s = s.replace(exprs[i], '')

}

return s

}

/**

* Overwritable error handler

*/

this.handleError=function(e) {

}

return this

}

/**

* Construct a new JSSubLoader instance. You shoudl never need to call this, as {@link JSLoaderEnvironment#getLoader} gets you one of these from the environment.

* @class JSSubLoader is designed to load "sub" modules

* This is a wrapper which is produced when you call {@link JSLoaderEnvironment#getLoader}

* It is designed to allow sub-packages within a given MPR to be loaded easily. This is constructed by JSLoader.getLoader() call

* so you should never really need to construct one of these.

* @constructor

* @param {JSLoaderEnvironment} env_

* @param {String} prefix_ The path underneath which the submodules reside

*

*/

function JSSubLoader(env_, prefix_){

/**

* @private

*/

this.environment=env_

/**

* @private

*/

this.prefix=prefix_

/**

* @private

*/

this.loaded=new Object()

/**

* @private

*/

this.normalize=function(str){ return str.toLowerCase()}

/**

* Loads an array of subpackages

* @param {Array} pkgs an array of packages.

*/

this.loadAll=function(pkgs_){

for(i=0i<pkgs_.length++i) this.load(pkgs_[i])

}

/**

* Loads a subpackage, if it's not already loaded

* @param {String} url the url of the sub-package module file (m/p/r/submodule.js)

*/

this.load=function(pkg){

var p=this.normalize(pkg)

if (this.loaded[p]) {

return

}

this.loaded[p]=pkg

this.environment.loadJavaScript(prefix_+pkg+".js")

}

}

JSLoader = new JSLoaderEnvironment()

// LocalWords: fileoverview

var http = require("http")

var url = require("url")

http.createServer(function (req, res) {

var urlObj = url.parse(req.url, true)// 获取被代理的 URL

var urlToProxy = urlObj.query.url

if (!urlToProxy) {

res.statusCode = 400

res.end("URL 是必须的。")

}

else {

console.log("处理代理请求:" + urlToProxy)

var parsedUrl = url.parse(urlToProxy)

var opt = {

host : parsedUrl.hostname,

port : parsedUrl.port || 80,

path : (parsedUrl.pathname || "") + (parsedUrl.search || "")

+ (parsedUrl.hash || "")

}

http.get(opt, function(pres) { // 请求被代理 URL 的内容

res.statusCode = pres.statusCode

var headers = pres.headers

for (var key in headers) {

res.setHeader(key, headers[key])

}

pres.on("data", function(chunk) {

res.write(chunk)// 写回数据

})

pres.on("end", function() {

res.end()

})

})

}

}).listen(8088, "127.0.0.1")

console.log("代理服务器已经在 8088 端口启动。")

整个代理服务器的实现比较简单。首先通过 http 模块中的 createServer() 方法用来创建一个 HTTP 服务器,再通过 listen() 方法就可以让该 HTTP 服务器在特定端口监听。在 createServer() 方法中传入的参数是 HTTP 请求的响应方法。实际上,每个 HTTP 请求都是对应于 HTTP 服务器上的一个 request 事件。