在Promise中设置的访问类属性

时间:2018-06-29 06:06:35

标签: javascript node.js ecmascript-6

来自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。

但是您看到的似乎是可能的比赛状况?

有没有办法解决这个问题...

谢谢

3 个答案:

答案 0 :(得分:3)

这不是比赛条件。一切正常。您的代码中有两个console.logs。第一个在承诺中,另一个在承诺之外。

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

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

例如

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

答案 1 :(得分:1)

因此您误解了关于诺言的某些事情。它们应用于异步代码,如下所示:

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和错误的比较可能会输出不正确,但是,如果将它们都放在相同的词法范围内,那么您仍然可以访问a或{{1 }}在您的诺言链范围之内。


侧面说明:您无需在类方法内使用箭头函数引用this_this。它们将按词法作用域,因此这将绑定到该函数的局部作用域。有关更多信息,请访问You Don't know JS

答案 2 :(得分:-1)

您正在尝试在创建承诺时(而不是在解决承诺时)设置isBound

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

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
  })
}

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

ADDITIONALLY 您的最后一个console.log()在您的诺言处理程序(.then())之外,因此它始终为null,因为在身份验证异步之前,该代码是同步运行的功能有时间完成。

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