Skip to content

step by step for sumeru.external

einsteinhx edited this page Nov 11, 2013 · 9 revisions

Sumeru提供了三方数据同步的方法,用来满足从三方网站/三方接口获取和同步数据的需求。 此文档通过一个例子来说明一次三方数据同步的过程。

1. 定义三方数据Model

app/model目录下定义model,三方model定义与普通model定义完全一致

Model.student = function(exports){
	exports.config = {
		fields : [
			{ name : 'name', type : 'text'},
			{ name : 'age', type : 'int', defaultValue : 0}
		]
	} 
}

2. publish三方数据

collection.extfind方法表示此collection为三方数据,处理数据方式不同。

//与普通的collection.find不同,三方数据的publish调用collection.extfind方法表示此collection为三方数据
fw.publish('student', 'pubext', function(/** arg1, arg2, arg3...*/ callback){

	var collection = this;
	collection.extfind('pubext', /** arg1, arg2, arg3...*/ callback);

});

3. 指定三方数据来源与解析方法

app/publish/下新增externalConfig.js文件(文件名任意,推荐使用externalConfig.js),用来指定三方数据来源与解析方法,需要注意必须为抓取回来的数据指定一个唯一标识uniqueColumn

/**
 * 获取三方数据信息,由开发者自定义
 */
function runnable(){
        //{Object} config是所有三方publish配置的容器
	var config = {};

	config['pubext'] = {
		//{String} uniqueColumn为三方数据唯一标识
		uniqueColumn : "name", 
                
                //{String} method为获取三方数据的请求方式,默认发get请求
                //如需通过post请求获取数据,声明method为"post"
                //method : 'post',

                //{Function} fetchUrl的参数就是订阅时发起的参数,返回值为pubext所抓取的url地址
		fetchUrl : function(/** arg1, arg2, arg3 */){
		        return 'http://some.host.com';
		},
                
                //{Function} resolve方法作用是将抓取回来的原始数据(originData)转化成为符合Model定义的数据(resolved)
		resolve : function(originData){

			var j = JSON.parse(originData);
			var resolved = j;
			
			return resolved;   
		},

                //{Number} fetchInterval为可选参数,用来指定抓取时间间隔,单位为ms
		fetchInterval : 60 * 1000,

                //{Boolean} buffer为可选参数,值为true时表示获取原始Buffer,否则获取原始数据字符串
		buffer : false
	}
        
        //最后需要声明此模块为归属为'external'
	return {
		type : 'external',
		config : config
	}

}

module.exports = runnable;

note:
如果想通过发送POST请求获取数据,需要在相应的config中声明method为"post",默认请求方式为GET请求。 并且fetchUrl方法需要做相应调整:

fetchUrl : function(arg1){
	return {
		hostname : 'some.host.com', //指定host
		path : '/fetch'             //指定path
                port : '12345'              //默认8080,非必须
	};
}

note:
POST请求的request body为subscribe的倒数第二个参数,如无参数,默认POST请求的request body为空字符串""; 添加request body时,同时需要为publish方法增加参数。

function getExt() {
        
        var requestBody = {test : 1};
	session.extStudent = env.subscribe('pubext', postData, function(collection, info){

		session.bind('extBlock', {
			data : collection.find().getData()
		});

	});

}

4. 指定三方增/删/改接口以及数据

如想将本地数据修改同步到三方,并且三方提供相应的post接口,可以在app/publish/externalConfig.js文件中,声明三方增/删/改接口以及数据:

较为紧凑的声明方式

声明中:

  • postUrl方法用来指定三方post接口的地址信息, 参数type为增量类型,增量类型为'insert','update','delete'三者之一;
  • prepare方法用来将增量数据转化成为符合三方POST接口要求的post数据,参数type同为增量类型,参数data为增量的实际数据。
/**
 *	三方数据POST请求信息,由开发者自定义
 */
function runnable(){

	var config = {}

	config['pubext'] = {
		
                /**
                 * 声明三方POST接口地址
                 * {String} type为'delete', 'insert', 'update'其中之一
                 * 如果subscribe时带参数,参数会按照subscribe顺序接在postUrl的参数中
                 */
                postUrl : function(type /** arg1, arg2, arg3... */){

			var options = {
				host : 'some.host.com',
				path : '/' + type
			}

			return options;

		},

		/**
                 * prepare方法将增量数据转化为符合三方要求的post数据。
		 * {String} type为增量操作,值为'delete', 'insert', 'update'其一;
		 * {Object} data为增量数据,如:{ name : 'user1', age : 26 }。
                 */
		prepare : function(type, data){
			var prepareData = {};  //prepareData为三方post所需的data
			if(type === "delete"){
				prepareData.name = data.name;
			}else if(type === "insert"){
				prepareData.name = data.name;
				prepareData.age = data.age;
			}else{
				prepareData.name = data.name;
				prepareData.age = data.age;
			}

			return prepareData;
		}
		
	}

	return {
		type : 'external',
		config : config
	}

}

module.exports = runnable;

较为工整的声明方式

较为工整的声明方式根据type将不同操作区分开来。

声明中:

  • deleteUrlinsertUrlupdateUrl三个方法作用等同于postUrl,返回不同操作下三方接口url信息。
  • onDeleteonInsertonUpdate三个方法作用等同于prepare方法, 返回经过处理,传给三方接口的post数据。
function runnable(){

	var config = {};

	config['pubext'] = {
                //arg1, arg2, arg3是subscribe时输入的参数
		deleteUrl : function(/** arg1, arg2, arg3... */){
			return {
				host : 'some.host.com',
				path : '/delete'
			}
		},

		insertUrl : function(/** arg1, arg2, arg3... */){
			return {
				host : 'some.host.com',
				path : '/insert'
			}
		},

		updateUrl : function(/** arg1, arg2, arg3... */){
			return {
				host : 'some.host.com',
				path : '/update'
			}
		},

		onInsert : function(data){
			var prepareData = {};
			prepareData.name = data.name;
			prepareData.age = data.age;
			return prepareData;
		},

		onUpdate : function(data){
			var prepareData = {}; 
			prepareData.name = data.name;
			prepareData.age = data.age;
			return prepareData;
		},

		onDelete : function(data){
			var prepareData = {}
			prepareData.name = data.name;
			return prepareData;
		}
	}

	return {
		type : 'external',
		config : config
	}

}

module.exports = runnable;

5. subsribe三方数据

subscribe方法与普通subscribe无差别,开发者只用关心所订阅的pubName,而不用区分数据来源。

function getExt() {
	session.extStudent = env.subscribe('pubext', function(collection, info){

		session.bind('extBlock', {
			data : collection.find().getData()
		});

	});

}

sumeru.external.post,sumeru.external.get和sumeru.external.sync接口

sumeru同样提供更底层,更灵活的post和get接口:

  • 向三方发送get请求
var url = "http://some.host.com";
var getCallback = function(data){
	console.log(data);
}
sumeru.external.get(url, getCallback);
  • 向三方发送post请求
var options = {
    host : "some.host.com",
    path : "/insert"
}

var postData = {
    name : sumeru.utils.randomStr(8),
    age : parseInt( 100 * Math.random())
}

var postCallback = function(data){
    console.log(data);
}

sumeru.external.post(options, postData, postCallback);
  • 主动和三方数据做同步

sync方法的将抓取最新的三方数据,并将新数据推送至前端。

var cb = function(data){
    console.log(data);
}
var url = "some.host.com";
sumeru.external.sync(modelName, pubName, url, cb);