gpt4 book ai didi

javascript - 将功能注入(inject)其他 Node.js 模块

转载 作者:行者123 更新时间:2023-12-03 22:42:28 24 4
gpt4 key购买 nike

我有一个 Node.js 应用程序(使用 sequelize 作为 orm),我尝试将它分成不同的模块,这些模块可以很容易地重用。这意味着我需要删除它们之间的一些依赖关系,但我在某一点上苦苦挣扎:

有一个名为“Account”的模块,它对其他模块应该(几乎)零依赖。它只提供基本的帐户功能。

然后是其他模块,它们依赖于帐户模块(没关系)。

目前,Account 模块依赖于其他模块,我想解决这个问题。现在,当创建帐户时,其他模块也必须在数据库中创建一些对象。这应该发生在同一个事务中,并且帐户模块不知道其他模块的某些信息。

目前,这如下所示:

AccountController.prototype.createAccount = function (data) {
// validation checks etc. omited

return db.sequelize.transaction(function (t) {
return Q.Promise(function (resolve, reject, notify) {
_createHash(pw, 10)
.then(function (hash) {
data.passwordHash = hash;

return _createAccount(data, t);
})
.then(function (account) {
// create user
return [account, _createUser(account, t)];
})
.spread(function (account, user) {
// create another object
return [account, user, _createXXX(account, t)]
})
.spread(function(account, user, xxx) {
// create 1 more object
return [account, user, xxx, _createYYY(account, t)];
})
.spread(function (account, user, xxx, yyy) {
resolve([account, user, xxx, yyy]);
})
.catch(reject);
});

});
};

现在,我只想在这个模块中创建 Account 对象,让其他模块独立创建它们的对象,但在同一个事务中。

首先,我考虑让 AccountController 在 Promise 链中发出一个“createAccount”事件,交出交易对象并让模块注册一些监听器。
但后来我注意到 EventEmitter 是异步工作的。

在 Node.js 中做这样的事情的最佳实践是什么?

最佳答案

好的,让我自己回答这个问题:

  • 尽管我读到了一些不同的东西,但我意识到 EventEmitter 不是异步的
  • 所以为这个任务使用事件基本上是有效的
  • 但是我遇到了问题,由于数据库调用,我的事件监听器异步。因此,我需要一种方法来等待所有事件监听器“真正”完成。
  • 我在 EventEmitter 的一个子类中引入了 promiseEmit() 函数,它允许监听器返回一个 Promise 并返回一个 Promise 本身,它只会在所有监听器 Promise 完成时完成。

  • 这是我想出的代码:
    'use strict';

    var EventEmitter = require('events');
    var util = require('util');
    var Q = require('q');

    function PromisedEventEmitter() {
    }

    util.inherits(PromisedEventEmitter, EventEmitter);

    PromisedEventEmitter.prototype.promisedEmit = function promisedEmit(type) {
    var er, handler, len, args, i, listeners;
    var promises = [];

    if (!this._events)
    this._events = {};

    // If there is no 'error' event listener then throw.
    if (type === 'error' && !this._events.error) {
    er = arguments[1];
    if (this.domain) {
    if (!er)
    er = new Error('Uncaught, unspecified "error" event.');
    er.domainEmitter = this;
    er.domain = this.domain;
    er.domainThrown = false;
    this.domain.emit('error', er);
    } else if (er instanceof Error) {
    throw er; // Unhandled 'error' event
    } else {
    throw Error('Uncaught, unspecified "error" event.');
    }
    return Q.all(promises);
    }

    handler = this._events[type];

    if (util.isUndefined(handler))
    return Q.all(promises);

    if (this.domain && this !== process)
    this.domain.enter();

    var promise;
    if (util.isFunction(handler)) {
    switch (arguments.length) {
    // fast cases
    case 1:
    promise = handler.call(this);
    break;
    case 2:
    promise = handler.call(this, arguments[1]);
    break;
    case 3:
    promise = handler.call(this, arguments[1], arguments[2]);
    break;
    // slower
    default:
    len = arguments.length;
    args = new Array(len - 1);
    for (i = 1; i < len; i++)
    args[i - 1] = arguments[i];
    promise = handler.apply(this, args);
    }
    promises.push(promise);
    } else if (util.isObject(handler)) {
    len = arguments.length;
    args = new Array(len - 1);
    for (i = 1; i < len; i++)
    args[i - 1] = arguments[i];

    listeners = handler.slice();
    len = listeners.length;
    for (i = 0; i < len; i++) {
    promise = listeners[i].apply(this, args);
    promises.push(promise);
    }
    }

    if (this.domain && this !== process)
    this.domain.exit();

    return Q.all(promises);
    };


    module.exports = PromisedEventEmitter;

    这基本上只是原始的 .emit 代码,我只是添加了一些 Promise 处理。我现在可以像原来的 EventEmitter 一样使用它,只需调用
    XXXController
    .promisedEmit("eventName", arg1, arg2, argN)]
    .then(function(){
    //...
    });

    关于javascript - 将功能注入(inject)其他 Node.js 模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33463965/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com