remote的写法支持es6的class么
zhengweikeng opened this issue · 5 comments
zhengweikeng commented
我在authRemote这样写
class Remote{
constructor(app) {
this.app = app
}
auth(token, cb){
cb()
}
}
module.exports = (app) => new Remote()
这样写rpc调用的时候,authRemote对象就是空的,拿不到auth方法。
但是改回prototype却可以。这是什么原因?
fantasyni commented
es6 的支持需要研究一下,我这里先记一下
39Er commented
遇到同样的问题,求解
seancheung commented
Remote不支持。Handler支持。
对于Remote,使用如下方法实现:
class Super {
calc() {
return 1;
}
}
class Child extends Super {
run() {
return this.calc() * 2;
}
}
//这是我们真正的remote handler
class Some extends Child {
login(name, pwd, next) {
next(null, {
key: this.calc(),
value: this.run()
});
}
}
// 创建一个function来实现支持
const Other = function () {
}
//使用Object.create来支持继承链, 否则Some里面是调用不到calc和run方法的. 如果你要copy的类是孤类, 这一步可以不做
Other.prototype = Object.create(Some.prototype);
//复制Some类中的自有方法. 不支持使用Object.defineProperty
Object.getOwnPropertyNames(Some.prototype).forEach(key => {
Other.prototype[key] = Some.prototype[key];
})
//替换构造器
Other.prototype.constructor = Other;
module.exports = () => new Other();
Remote和Handler都通过pomelo-loader
来加载, 但是Remote是通过pomelo-rpc
来调用的. 可能其中有进行ownProperty
的判断
redelva commented
如果能提供全套的es6支持就好了,现在已经不习惯callback了
在 2017-07-30 18:54:16,"Sean" <notifications@github.com> 写道:
Remote不支持。Handler支持。还在查。
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.
seancheung commented
@redelva
Remote
和 Handler
的基类给你
module.exports = class Remote {
/**
* Creates an instance of Remote
*
*/
constructor(app) {
this.app = app;
this.logger = require('pomelo-logger').getLogger(this.constructor.name);
}
/**
* Create an instance of this type
*
* @static
* @returns
*/
static new() {
const Type = this;
return function () {
const Export = function () {}
const remote = new Type(...arguments);
Export.prototype = Object.create(Type.prototype);
Object.getOwnPropertyNames(Type.prototype).forEach(key => {
if (typeof Type.prototype[key] === 'function' && key !== 'constructor') {
Export.prototype[key] = function () {
const result = remote[key](...arguments);
const next = arguments[arguments.length - 1];
if (Promise.is(result)) {
result.asCallback(next);
}
}
}
});
return new Export(...arguments);
}
}
}
module.exports = class Handler {
/**
* Creates an instance of Handler
*
*/
constructor(app) {
this.app = app;
this.logger = require('pomelo-logger').getLogger(this.constructor.name);
}
/**
* Create an instance of this type
*
* @static
* @returns
*/
static new() {
const Type = this;
return function () {
const Export = function () {}
const handler = new Type(...arguments);
Export.prototype = Object.create(Type.prototype);
Object.getOwnPropertyNames(Type.prototype).forEach(key => {
if (typeof Type.prototype[key] === 'function' && key !== 'constructor') {
Export.prototype[key] = function () {
const next = arguments[arguments.length - 1];
const result = handler[key](...arguments);
if (Promise.is(result)) {
result.asCallback(next);
}
}
}
});
return new Export(...arguments);
}
}
}
在Handler
或Remote
的方法中返回Promise
, 就会被自动处理并调用next
传递异常错误或正确结果;
若不返回Promise
, 则需要手动调用next
回调. 不可以既调用next
回调又返回Promise
.
Remote
用法示例
module.exports = class GameRemote extends Remote {
/**
* Raw query commands.
* Only available in dev mode. Can be harmful
*
* @param {string|string[]} sql
* @param {string|string[]} redis
* @param {string|number} id
*/
query(sql, redis, id) {
const array = [];
if (sql) {
array.push(this.app.get('db.main').query(sql));
}
if(redis) {
array.push(this.app.get('db.cache').query(redis));
}
if(id) {
const { User } = require('@/database/models');
array.push(User.destroy({ where: {id}, individualHooks: true}));
}
return Promise.all(array);
}
}.new();
Handler
用法类似
注意, rpc
方法是Proxy
, 不支持Promise
错误(next不会被执行, 导致timeout
):
return this.app.rpc.auth.remote.login(session, msg.username, msg.password)
正确(手动调用next
):
this.app.rpc.auth.remote.login(session, msg.username, msg.password, next)
或者Promise
化(返回Promise
):
return Promise.promisify(this.app.rpc.auth.remote.login)(session, msg.username, msg.password)
如果需要将session中的方法Promise
化, 添加以下Filter
即可
promisify.js
module.exports = {
/**
* Before
*
* @param {any} msg
* @param {any} session
* @param {Function} next
*/
before(msg, session, next) {
Promise.promisifyAll(session);
next();
}
}
app.js
app.before(require('@/filters/promisify'));
调用
session.pushAllAsync()