带回调的链类方法?

时间:2015-10-19 21:43:14

标签: javascript node.js promise

在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那样有一种“承诺模式”,但在查看代码之后,我仍然不确定它们是如何做到的。

3 个答案:

答案 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