节点异步执行

node executes asynchronously

在我的 Express 应用程序中,我使用 node_acl

实现 ACL

我的 acl.js 看起来像:

var mongoose = require('mongoose'),
node_acl = require('acl'),
acl;

mongoose.connect('mongodb://127.0.0.1:27017/aclExample', function _mongo_connected(){
    var mongoBackend = new node_acl.mongodbBackend(mongoose.connection.db, 'acl_');
    acl = new node_acl(mongoBackend);

    
    console.log("ACL: ",acl);
});
set_roles();


function set_roles() {
    //set permissions for roles
    acl.allow([
        {
            roles: 'a',  //roles
            allows: [
                {resources: '/fe', permissions: ['put', 'delete']},
            ]   //permissions
        },
        {
            roles: 'b',
            allows: [
                {resources: '/fe/api', permissions: 'post'}
            ]
        },
        {
            roles: 'c',
            allows: [
                {resources: '/', permissions: ['post', 'put']}
            ]
        },
        {
            roles: 'd',
            allows: [
                {resources:'/fe', permissions: ['get', 'post']}
            ]
        }
    ]);
    acl.addUserRoles(420, 'b').then( ()=> console.log('added user'))
    .catch(err => console.error(err));
  
    acl.addUserRoles(520, 'a').then( ()=> console.log('added user'))
    .catch(err => console.error(err));
  
    //acl.isAllowed(userId, reso, pem);
  }

module.exports = acl;

和我的 app.js:

var acl = require('@root/fe-server/middlewares/fe.middleware.acl.js');
var express = require('express');
var app = express();
console.log("ACL: ",acl);

我得到的输出如下所示:

ACL:  undefined
added user
added user

我可以理解节点在建立连接和创建数据库之前在 app.js 中执行控制台语句,但我似乎无法弄清楚如何解决这个问题。 任何帮助将不胜感激。

正如您自己所说,mongoose.connect 需要一些时间,因此它接受一个回调函数,一旦完成就会执行,您已经在使用它了。

在该回调函数中,您创建了 acl 资源,这意味着任何使用 acl 变量的内容也必须从该回调中执行(直接或间接)。所以在你的情况下你必须做这样的事情:

acl.js

const mongoose = require('mongoose');
const node_acl = require('acl');

const connect = (callback) => {
  mongoose.connect('mongodb://127.0.0.1:27017/aclExample', (err) => {
    if (err) return callback(err);

    const mongoBackend = new node_acl.mongodbBackend(mongoose.connection.db, 'acl_');
    const acl = new node_acl(mongoBackend);

    set_roles(acl).then(() => callback(null, acl)).catch(callback);
  });
};

const set_roles = (acl) => {
  acl.allow([ /* stuff */ ]);

  return Promise.all([
    acl.addUserRoles(420, 'b').then(() => console.log('added user b')),
    acl.addUserRoles(520, 'a').then(() => console.log('added user a')),
  ])
};

module.exports = connect;

main.js:

var connectACL = require('acl.js');
var express = require('express');
var app = express();

connectACL((err, acl) => {
  console.log('ACL: ', acl);
});

重要的变化是 require('acl.js') 现在 returns 一个接受回调的函数,这样您就可以在创建后安全地使用 acl

您还可以看到 acl 使用另一种处理异步性的方法,称为 "Promises"(.then.catch 的东西)。两者都是有效的选项,但您通常希望决定只使用一个并尽快转换另一个(就像我在这里使用 .then(() => callback(null, acl)).catch(callback) 所做的那样)。 但是,当您处理异步函数时,您将需要其中之一,因为您已确保您的代码以正确的顺序执行。