我正在创建一个“类”,用于发出error
,data
,downloadFile
和initialize
等事件。发出请求后会触发每个事件,并且每个事件都由具有相同名称的方法触发:
class MyClass extends EventEmitter {
constructor(data) {
this.data = data
this.initialize()
.then(this.downloadFile)
.then(this.data)
.catch(this.error)
}
initialize() {
const req = superagent.post('url...')
superagent.send(data)
const res = await req // this will actually fire the request
this.emit('initialize')
this.url = res.body
return res
}
downloadFile() {
const req = superagent.put(this.url)
const res = await req; // this will actually fire the request
req.on('progress', (progress) => this.emit('downloadFile', progress)
//
// save to disk
//
return res
}
data() {
// Next in the sequence. And will fire the 'data' event: this.emit('data', data)
}
error(err) {
this.emit('error', err)
}
}
之后我会调用数据方法。我的疑问是:是否有一种设计模式可以在不使用Promise的情况下按顺序调用事件?目前我正在使用链接,但我觉得这不是最好的方法,也许我错了。
this.initialize()
.then(this.downloadFile)
.then(this.data)
.catch(this.error)
但我觉得这可能是一种更好的方法。
bergi问题的答案:
a)为什么使用类语法?
因为从EventEmitter继承更容易,而且我认为它比使用构造函数更具可读性 功能,例如:
function Transformation(data) {
this.data = data
}
// Prototype stuffs here
b)如何使用此代码
我正在创建一个与我的API进行交互的客户端。意思是用户可以看到后台发生的事情。 E.g:
const data = {
data: {},
format: 'xls',
saveTo: 'path/to/save/xls/file.xls'
}
const transformation = new Transformation(data)
// Events
transformation.on('initialize', () => {
// Here the user knows that the transformation already started
})
transformation.on('fileDownloaded', () => {
// Here the file has been downloaded to disk
})
transformation.on('data', (data) => {
// Here the user can see details of the transformation -
// name,
// id,
// size,
// the original object,
// etc
})
transformation.on('error', () => {
// Here is self explanatory, if something bad happens, this event will be fired
})
c)该怎么办?
用户可以将包含数据的对象转换为Excel。
答案 0 :(得分:1)
听起来您正在创建的transformation
对象仅供调用者用于侦听事件。用户不需要具有要获取的属性的class
实例或要调用的方法。所以不要做一个。 KISS。
function transform(data) {
const out = new EventEmitter();
async function run() {
try {
const url = await initialise();
const data = await downloadFile(url);
out.emit('data', data);
} catch(err) {
out.emit('error', err);
}
}
async function initialise() {
const req = superagent.post('url...')
superagent.send(data)
const res = await req // this will actually fire the request
out.emit('initialize')
return res.body
}
async function downloadFile(url) {
const req = superagent.put(url)
req.on('progress', (progress) => out.emit('downloadFile', progress)
const res = await req; // this will actually fire the request
//
// save to disk
//
return data;
}
run();
return out;
}
可能更简单的是省略(仅限一次?)data
和error
事件,只是返回一个承诺,与事件发射器一起用于进度通知:
return {
promise: run(), // basically just `initialise().then(downloadFile)`
events: out
};
答案 1 :(得分:0)
如果您想要另一种方式按顺序调用事件,并且如果您使用支持ES7的Node.js版本,则可以执行以下操作:
class MyClass extends EventEmitter {
constructor(data) {
this.data = data;
this.launcher();
}
async launcher() {
try {
await this.initialize();
await this.downloadFile();
await this.data();
}
catch(err) {
this.error(err);
}
}
initialize() {
const req = superagent.post('url...');
superagent.send(data);
this.emit('initialize');
this.url = req.body;
return req;
}
downloadFile() {
const req = superagent.put(this.url);
req.on('progress', (progress) => this.emit('downloadFile', progress)
//
// save to disk
//
return req;
}
data() {
// Next in the sequence. And will fire the 'data' event: this.emit('data', data)
}
error(err) {
this.emit('error', err)
}
}
说明:在函数内部代替await
你的Promise,只需在根级别为它们返回Promises和await
。