使用返回承诺的多个步骤来定制自定义查找器

时间:2014-08-05 12:29:47

标签: node.js promise sequelize.js

我对节点很新(不仅仅是一个玩具项目)而且我正在努力解决如何正确使用Sequelize的问题。它有一个由promise驱动的API,在它返回的promise中一直使用'error'和'success'方法。

我编写了一个自定义查找程序,它涉及三个查询以查找记录,执行原子更新,如果成功,则重新加载记录。

我最初使用易于理解的回调方法编写了这个,但因为没有与Sequelize使用的契约相匹配的契约,我想重写它以返回带有成功/错误方法的Promise。有什么指针吗?看起来Sequelize已经采用了Bluebird并对其进行了定制,但我不确定是否有一种打算让开发人员自己使用该功能的方式。

/**
 * Acquire a build in the 'queued' state and transition it to 'pending'.
 *
 * @return {Promise}
 *   a promise for the executed query
 */
Build.acquireQueued = function(callback) {
  Build
    .find({where: {status:'queued'}})
    .success(function(build){
      if (!build)
        return callback();

      Build
        .update(
          {status:'pending'},
          {id:build.id, status:build.status},
          {returning:true}
        )
        .success(function(result){
          var affectedRows = result[0];

          if (affectedRows == 0)
            return callback();

          build.reload().success(function(build){
            callback(undefined, build);
          });
        })
        .error(callback);
    })
    .error(callback);
};

我目前必须如下调用:

Build.acquireQueued(function(err, build){
  // maybe got a build
});

但是因为那看起来不像Sequelize,我希望能够像这样称呼它:

Build
  .acquireQueued()
  .success(function(build){
    // definitely got a build
  })
  .error(function(err){
    // splosion!
  });

1 个答案:

答案 0 :(得分:0)

与往常一样,我在发布问题后很快就明白了。您需要使用Sequelize.Utils.CustomEventEmitter。你给它一个接受EventEmitter的函数,然后在你完成时调用emitter.emit('success', things)

/**
 * Acquire a job in the 'queued' state and mark it 'pending'.
 *
 * @return {Promise}
 *   a promise for the executed query
 */
Build.acquireQueued = function() {
  return new db.CustomEventEmitter(function(emitter){
    Build
      .find({where: {status:'queued'}})
      .success(function(build){
        if (!build)
          return emitter.emit('success');

        Build
          .update(
            {status:'pending'},
            {id:build.id, status:build.status},
            {returning:true}
          )
          .success(function(result){
            var affectedRows = result[0];

            if (affectedRows == 0)
              return emitter.emit('success');

            // Final return value
            build.reload().proxy(emitter);
          })
      })
  })
  .run();
};