Node.js 节点代码没有阻塞?

Node.js 节点代码没有阻塞?,node.js,typescript,dynogels,Node.js,Typescript,Dynogels,我有一个构造函数,它使用promisified dynogels从DynamoDB获取数据来填充对象的部分属性。 因此,在实例化该对象的实例后,不会填充该属性,下面是代码的摘录: export class QueryAuthoriser { authPerms: [AuthPerms]; constructor (data: string) { AuthPermsDDB.scan().execAsync().then ( (perms) => { perms.

我有一个构造函数,它使用promisified dynogels从DynamoDB获取数据来填充对象的部分属性。 因此,在实例化该对象的实例后,不会填充该属性,下面是代码的摘录:

export class QueryAuthoriser {
  authPerms: [AuthPerms];

  constructor (data: string) {
    AuthPermsDDB.scan().execAsync().then ( (perms) => {
      perms.Items.forEach(element => {
        this.authPerms[element.name] = <AuthPerms> element.attrs
      })
    }).catch (err => {
      console.log ('%%%%%%%%%%%%%% Err loading authPerms: ', err)
    })
  }

  authFieldAccess (fieldName: string, args?:any): Promise<boolean> {
    return new Promise ((resolve, reject) => {
      console.log ('________________ authFieldAccess called for: ', fieldName)
      console.log ('________________ this.authPerms entry: ', this.authPerms[fieldName])
      resolve (true)
    })
[...]
}
导出类查询作者{
authPerms:[authPerms];
构造函数(数据:字符串){
AuthPermsDDB.scan().execAsync()。然后((perms)=>{
perms.Items.forEach(元素=>{
this.authPerms[element.name]=element.attrs
})
}).catch(错误=>{
console.log('%Err加载authPerms:'时出错,错误)
})
}
authFieldAccess(字段名:string,args?:any):承诺{
返回新承诺((解决、拒绝)=>{
console.log('''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
console.log('''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
解析(真)
})
[...]
}
因此,当调用
authFieldAccess
方法时,字段
this.authPerms
未定义。如何修复此问题


谢谢,我正在艰难地学习node和typescript:O你通常不想在构造函数中执行异步操作,因为这会使创建一个对象变得复杂,然后知道异步操作何时完成,或者是否有错误,因为你需要允许构造函数返回对象,而不是一个承诺告诉您异步操作何时完成

有几种可能的设计选项:

选项#1:不要在构造函数中执行任何异步操作。然后,添加一个具有适当名称的新方法来执行异步操作并返回承诺

在您的情况下,可以将新方法设置为返回承诺的
scan()
。然后,您可以通过创建对象,然后调用scan,然后使用返回的承诺来使用对象,以了解数据何时有效

我自己也不知道TypeScript,因此我将给出您代码的修改版本,但无论是TypeScript还是普通Javascript,概念都是一样的:

export class QueryAuthoriser {
  authPerms: [AuthPerms];

  constructor (data: string) {
  }

  scan () {
    return AuthPermsDDB.scan().execAsync().then ( (perms) => {
      perms.Items.forEach(element => {
        this.authPerms[element.name] = <AuthPerms> element.attrs
      })
    }).catch (err => {
      console.log ('%%%%%%%%%%%%%% Err loading authPerms: ', err)
    })
  }

}

// usage
let obj = new QueryAuthoriser(...);
obj.scan(...).then(() => {
    // the object is full initialized now and can be used here
}).catch(err => {
    // error here
})
导出类查询作者{
authPerms:[authPerms];
构造函数(数据:字符串){
}
扫描(){
返回AuthPermsDDB.scan().execAsync()。然后((perms)=>{
perms.Items.forEach(元素=>{
this.authPerms[element.name]=element.attrs
})
}).catch(错误=>{
console.log('%Err加载authPerms:'时出错,错误)
})
}
}
//用法
设obj=newqueryauthoriser(…);
对象扫描(…)。然后(()=>{
//对象现在已完全初始化,可以在此处使用
}).catch(错误=>{
//这里出错
})
选项#2:在构造函数中启动异步操作,并在实例数据中使用承诺,以便调用方知道何时完成所有操作。

export class QueryAuthoriser {
  authPerms: [AuthPerms];

  constructor (data: string) {
    this.initialScan = AuthPermsDDB.scan().execAsync().then ( (perms) => {
      perms.Items.forEach(element => {
        this.authPerms[element.name] = <AuthPerms> element.attrs
      })
    }).catch (err => {
      console.log ('%%%%%%%%%%%%%% Err loading authPerms: ', err)
    })
  }

}

// usage
let obj = new QueryAuthoriser(...);
obj.initialScan.then(() => {
    // the object is full initialized now and can be used here
}).catch(err => {
    // error here
});
export createQueryAuthorizer;

function createQueryAuthorizer(...) {
    let obj = new QueryAuthorizer(...);
    return obj._scan(...).then(() => {
        // resolve with the object itself
        return obj;
    })
}

class QueryAuthoriser {
  authPerms: [AuthPerms];

  constructor (data: string) {
  }

  _scan () {
    return AuthPermsDDB.scan().execAsync().then ( (perms) => {
      perms.Items.forEach(element => {
        this.authPerms[element.name] = <AuthPerms> element.attrs
      })
    }).catch (err => {
      console.log ('%%%%%%%%%%%%%% Err loading authPerms: ', err)
    })
  }

}

// usage
createQueryAuthorizer(...).then(obj => {
    // the object is fully initialized now and can be used here
}).catch(err => {
    // error here
});
导出类查询作者{
authPerms:[authPerms];
构造函数(数据:字符串){
this.initialScan=AuthPermsDDB.scan().execAsync()。然后((perms)=>{
perms.Items.forEach(元素=>{
this.authPerms[element.name]=element.attrs
})
}).catch(错误=>{
console.log('%Err加载authPerms:'时出错,错误)
})
}
}
//用法
设obj=newqueryauthoriser(…);
对象初始化扫描。然后(()=>{
//对象现在已完全初始化,可以在此处使用
}).catch(错误=>{
//这里出错
});
选项#3:使用工厂函数返回解析为对象本身的承诺。

export class QueryAuthoriser {
  authPerms: [AuthPerms];

  constructor (data: string) {
    this.initialScan = AuthPermsDDB.scan().execAsync().then ( (perms) => {
      perms.Items.forEach(element => {
        this.authPerms[element.name] = <AuthPerms> element.attrs
      })
    }).catch (err => {
      console.log ('%%%%%%%%%%%%%% Err loading authPerms: ', err)
    })
  }

}

// usage
let obj = new QueryAuthoriser(...);
obj.initialScan.then(() => {
    // the object is full initialized now and can be used here
}).catch(err => {
    // error here
});
export createQueryAuthorizer;

function createQueryAuthorizer(...) {
    let obj = new QueryAuthorizer(...);
    return obj._scan(...).then(() => {
        // resolve with the object itself
        return obj;
    })
}

class QueryAuthoriser {
  authPerms: [AuthPerms];

  constructor (data: string) {
  }

  _scan () {
    return AuthPermsDDB.scan().execAsync().then ( (perms) => {
      perms.Items.forEach(element => {
        this.authPerms[element.name] = <AuthPerms> element.attrs
      })
    }).catch (err => {
      console.log ('%%%%%%%%%%%%%% Err loading authPerms: ', err)
    })
  }

}

// usage
createQueryAuthorizer(...).then(obj => {
    // the object is fully initialized now and can be used here
}).catch(err => {
    // error here
});
导出createQueryAuthorizer;
函数createQueryAuthorizer(…){
设obj=newqueryauthorizer(…);
返回obj.\U扫描(…)。然后(()=>{
//解析对象本身
返回obj;
})
}
类查询作者{
authPerms:[authPerms];
构造函数(数据:字符串){
}
_扫描(){
返回AuthPermsDDB.scan().execAsync()。然后((perms)=>{
perms.Items.forEach(元素=>{
this.authPerms[element.name]=element.attrs
})
}).catch(错误=>{
console.log('%Err加载authPerms:'时出错,错误)
})
}
}
//用法
createQueryAuthorizer(…)。然后(obj=>{
//对象现在已完全初始化,可以在此处使用
}).catch(错误=>{
//这里出错
});

我更喜欢选项#3有几个原因。它捕获了工厂函数中的一些共享代码,每个调用方都必须在其他方案中执行这些代码。它还阻止在对象正确初始化之前访问对象。其他两个方案只需要文档和编程规程,很容易被误用ed.

谢谢@jfriend00,它工作得很好。虽然这段代码会阻止
createQueryAuthorizer
方法,但我的意图是对DB进行异步调用,只在我第一次需要数据时等待,但只在第一次等待,因为数据需要多次。不过,我会尝试更改实现。@CarlosDelgado-此处没有任何内容会阻塞,因此我不太清楚您的意思。
createQueryAuthorizer()
方法立即返回并返回一个承诺。在对象正确初始化之前,您不能使用它。如果代码的其他部分也要使用相同的对象,则它们可以等待相同的承诺。