访问在承诺内部设置的类属性



来自PHP的沉重背景,我正在努力解决node/js的某些方面。

const ldap = require('ldapjs');
class LdapClient {
constructor({
url,
}) {
this.isBound = null;
this.client = ldap.createClient({ url });
}
authenticate(credentials) {
const _this = this;
return new Promise((resolve, reject) => {
return this.client.bind(credentials.username, credentials.password, (err, res) => {
if (err) {
this.client.unbind();
return reject(err);
}
_this.isBound = true;
return resolve(res);
});
});
}
}
const client = new Client({url: ''})
const credentials = {
'username': '',
'password': ''
}
client.authenticate(credentials)
.then(() => {
console.log('authenticated');
console.log('race = ' + client.isBound); // SHOWS TRUE
})
.catch(e => {
console.log(e);
})
console.log(client.isBound); // SHOWS NULL... WANT TRUE (RACE ISSUE as consoles before PROMISE)

我正在尝试访问 promise 返回之外的isBound属性,成功后在身份验证方法中将其设置为 true。

但是,如您所见,似乎可能存在竞争条件?

有没有办法处理这个问题...

谢谢

这不是竞争条件。它按预期工作正常。代码中有两个console.logs。第一个在承诺中,另一个在承诺之外。

您的调用进入异步模式,最后一个console.log按顺序作为下一个命令按顺序执行,当时变量的值null。您的变量稍后会以正确的值解析。

如果必须执行进一步的操作,则必须在Client方法的.then()部分中执行此操作,该部分仅在Promise解析后执行。

例如

Client().then() {//all of your post response related logic should be here}

所以你误解了承诺。它们旨在用于异步代码,如下所示:

let p = new Promise(resolve => setTimeout(resolve, 1000, 'here'))
p.then(console.log)
//in one second 'here'

如您所见,直到承诺解决之后,然后才会真正发生。使用异步代码,无论何时调用解析。

因此,代码中发生的情况如下:

Create Promise -> set event loop callback
console.log(isBound) // false, but happens first because it's called sync
Promise resolves // true

因此,在您的承诺决议中,您甚至可以成功检查它的第一个地方。如果您从呼叫中返回它,则可以将其链接到那里,并确保稍后继续使用范围。

let a = 0
let p = Promise.resolve(a)
.then(a =>{
a += 2;
return a;
})
.then(a => console.log(a) || a)
console.log(a) // 0
p == p.then(a =>{
a += 4;
return a;
})
.then(console.log) // false because promises aren't equal and .then/.catch return new promise chains
// 2
// 6

由于事件循环,2,6 和错误的比较可能会打印出无序,但是如果您将其全部保留在相同的词汇范围内,那么您仍然可以访问承诺链范围内的athis


旁注:您无需在类方法中引用_thisthis箭头函数。它们将在词法上作用域,因此这将绑定到该函数的本地作用域。更多信息可以在你不知道JS中找到

您尝试设置isBound创建承诺的时间,而不是解决承诺的时间。

您可以将其存储在变量中,对其调用.then(),然后在该点返回 promise 链,而不是直接从authenticate()方法返回 promise。

authenticate(credentials) {
// create your promise and store it
let authPromise = new Promise((resolve, reject) => {
...
})
// handle the promise and set isBound before returning the chain
return authPromise.then(res => {
_this.isBound = true
return res
})
}

这可以用更少的行来写,但这是为了说明在返回之前的承诺链和拦截。

此外,您的最终console.log()在您的 promise 处理程序(.then()(之外,因此它始终为 null,因为该代码在身份验证异步函数有时间完成之前同步运行。

client.authenticate(credentials)
.then(res => {
// you MUST do all your async-dependant operations inside
// promise handlers like this
console.log(client.isBound);
})

最新更新