在ORM中实现(继承)Promise接口

时间:2017-01-17 11:38:16

标签: javascript promise bluebird odm

我想宣传ODM / ORM。如何使用find()insert()update()等其他方法实现promise接口。所以你可以做到

var Users = Collection('users')
Users.find({name: 'joe'})
  .then(users => users.update({name: 'jim'))
  .then(console.log)

我想继承自Promise,但是如何自定义then()以返回您的ORM实例,以确保我们使用按顺序进行的所有查询来处理实例。 现在我正在使用合成但是我必须代理每个方法调用都变得难看。

例如:

var Promise = require('bluebird')

var Collection = function(Storage, name) {
    this.promise = new Promise(function(resolve, reject) {
            self.resolve = resolve
            self.reject = reject
        })
}

Collection.prototype.find = function(query) {
    // async query stuff here
    Storage.doAsyncQueryStuff(function (err, results) {
        err && this.reject(err)
        this.resolve(results)
    })
}

Collection.prototype.then = function(callback) {
    var self = this
    this.promise.then(function() {
        callback && callback.apply(self, arguments)
    })
    return this
}

我想做的是:

var inherits = require('util').inherits
var Promise = require('bluebird')

var Collection = function(Storage, name) {
    var self = this
    // error here
    Promise.call(
        this,
        function(resolve, reject) {
            self.resolve = resolve
            self.reject = reject
        })
}
inherits(Collection, Promise)

我似乎无法将Promise初始化。或者我应该以不同的方式做这件事?

1 个答案:

答案 0 :(得分:1)

经过一些研究后,我发现在ORM实例中继承承诺不是一个好主意,因为以下内容:

Promises以递归方式解析,每个都返回从最后一个解析的new promise

例如:

var debug = console.log

var promise1 = new Promise((r, e) => {
    r(1)
})
var promise2 = new Promise((r, e) => {
    r(2)
})

var promise3 = promise1.then(data => promise2)

debug('promise1 === promise1', promise1 === promise1) // true
debug('promise3 === promise1', promise3 === promise1) // false
debug('promise3 === promise2', promise3 === promise2) // false

promise1将首先解析promise2并使用已解析的值作为promise1的分辨率值。然后,promise1将返回一个解析为promise1值的新promise(promise3)。

这很重要,因为承诺解决状态是不可变的,但承诺是可链接的。

要在ODM中有效地为每个then()调用返回一个新的promise,同时保留它的当前状态,需要进行优化,例如使ORM状态数据不可变或从全局存储(注册表)引用,同时保持它的当前{{1唯一的(过滤器,排序,加载的关系)等。将promise接口像then(),catch()组合到ORM上更简单,因为Promise规范是非常宽容的。

由于检查只允许Promise类型的Object创建实例,因此阻止了通过继承扩展bluebird。 https://github.com/petkaantonov/bluebird/issues/325

Bluebird以及FF,Chrome和Node.js内置的Promise无法通过ES5继承扩展。它们都需要Promise实例来实例化。

ECMA262定义了可继承的Promise对象。 http://www.ecma-international.org/ecma-262/6.0/#sec-promise-constructor

使用ES6类语法,您可以扩展内置的浏览器承诺。

query

这可能适用于使用Babel的Node.js。

您可以通过直接在ES5中设置class MyPromise extends Promise {} 属性来扩展bluebird和内置promise。

__proto__

虽然我不推荐它,但/** * @class MyPromise * @extends Promise */ var MyPromise = function () { var resolve, reject var promise = new Promise(function(_resolve, _reject) { resolve = _resolve reject = _reject }) promise.__proto__ = this.__proto__ promise.resolve = resolve promise.reject = reject return promise } MyPromise.prototype = Object.create(Promise.prototype, { constructor: { value: MyPromise } }) MyPromise.prototype.call = function() { this.resolve(new Date) } MyPromise.all = Promise.all MyPromise.cast = Promise.cast MyPromise.reject = Promise.reject MyPromise.resolve = Promise.resolve module.exports = MyPromise 不是标准虽然广泛支持。