在Node.js中,当最佳实践使用回调时,如何将类方法链接在一起?
在我的PHP时代,我通常会这样做:
class MyClass {
function get() {
// fetch some data from an API endpoint
return this;
}
function set(property, value) {
// Set the property to some value on the object
return this;
}
function save() {
// Save the data to database
return this;
}
}
$myObject = new MyClass();
$myObject->set('something','taco')->save();
这种非常常见的面向对象方法允许您将方法链接在一起多次。
使用Node.js时,你还能以某种方式进行链接吗?或者你最终还是在回调地狱?每一个“链”都是一个嵌套的回调?
或者我只是需要将我的脚本包装在Promises中?
new Promise(function(resolve, reject){
var myObject = new MyClass();
myObject.set('something','taco');
resolve(myObject);
}).then(function(myObject){
myObject.save();
});
你应该这样做吗?有没有办法将这个更深入地融入我的班级,所以我不必每次都把它包含在承诺中?我已经看到一些库像https://github.com/sindresorhus/got那样有一种“承诺模式”,但在查看代码之后,我仍然不确定它们是如何做到的。
答案 0 :(得分:4)
使用return this
进行同步调用。
使用Promise
或回调进行异步调用。
class MyClass {
get() {
return new Promise((resolve, reject)=> {
// Make Request and call resolve( result ) or reject( err )
});
}
set( property, value ) {
this[property] = value;
return this;
}
save() {
return new Promise((resolve, reject)=> {
// Make Request and call resolve( result ) or reject( err )
});
}
}
var myObject = new MyClass();
myObject
.set('something', 'taco')
.save()
// resolve handler
.then(( saveResult )=> {
console.log( saveResult );
return myObject.get();
})
// resolve handler
.then(( getResult )=> {
console.log( getResult );
})
// reject handler
.catch(( error )=> { });

答案 1 :(得分:1)
您的方法可能是这样的:
(async function() {
class MyClass {
constructor() {
this._lastPromise = Promise.resolve();
this.a = 0;
}
set(property, value) {
var self = this;
return new Promise(async (resolve, reject) => {
console.log("self.%s set to: %s", property, value);
await new Promise((resolve, reject) => {
setTimeout(resolve, 5000);
});
self[property] = value;
resolve(self);
});
}
save() {
var self = this;
return new Promise(function(resolve, reject) {
console.log(self.a + " Saved");
resolve(self);
});
}
}
var myObject = new MyClass();
console.log("before");
await myObject
.set("a", "1")
.then(self => self.save())
.then(self => self.set("a", "5"))
.then(self => self.save());
console.log("after");
})();
答案 2 :(得分:0)
您可以存储特殊的私有成员变量__lastPromise
。最初它将默认解决。但是,任何执行任务的函数都会使用返回承诺更新它。此外,函数本身只会在 之前 承诺已经解决后执行任务。
像这样:
save() {
// only after __lastPromise has resolved
var newPromise = __lastPromise.then(function() {
// Do stuff here
});
// update __lastPromise with the newly returned promise
this.__lastPromise = newPromise;
// return this for regular chaining
return this;
}
完整课程:
class MyClass {
constructor(){
this.__lastPromise = Promise.resolve();
this.a = 0;
}
set(property, value) {
var self = this;
self.__lastPromise = self.__lastPromise.then(function() {
return new Promise(function(resolve, reject) {
console.log('self.%s set to: ', property, value);
self[property] = value;
resolve();
});
});
return self;
}
save() {
var self = this;
self.__lastPromise = self.__lastPromise.then(function() {
return new Promise(function(resolve, reject) {
console.log('Saved');
resolve();
});
});
return self;
}
}
var myObject = new MyClass();
myObject.set('a', '1').save().set('a', '2').save();
this.a set to: 1
Saved
this.a set to: 2
Saved