ES6异步/等待类

vaj*_*ehu 10 javascript node.js async-await ecmascript-6 es6-promise

我正在尝试创建一个发送帖子请求(登录)的类,保存cookie并将该cookie用于其他操作,例如下载文件.

我创建了一个本地服务器,它将接收一个带有用户和密码的post http方法,并且/download只有在用户登录时才会访问一个名为的路由器,否则它将返回you need to log in.

问题:这是我班级的原型(手前):

const request = require('request-promise-native')

class ImageDownloader {
  constructor(username = null, password = null) {
    this.username = username
    this.password = password
    this.cookie = request.jar()

    this.init()
  }

  init() {
    // login and get the cookie
  }

  download() {
    // needs the cookie
  }

  query() {
    // needs the cookie
  }
}
Run Code Online (Sandbox Code Playgroud)

正如你在上面的代码中看到的,我需要两个操作的cookie download,query所以我想创建一个init方法来执行初始操作,如登录并在构造函数中调用它,这样它将被初始化并放入cookie在变量this.cookie上随处可用,但它不起作用,似乎init是在每隔一个方法之后调用它.

const request = require('request-promise-native')

class ImageDownloader {
  constructor(username = null, password = null) {
    this.username = username
    this.password = password
    this.cookie = request.jar()

    this.init()
  }

  async init() {
    await request({
      uri: 'http://localhost/login',
      jar: this.cookie,
      method: 'post',
      formData: {
        'username': 'admin',
        'password': 'admin'
      }
    }).catch(e => console.error(e))
  }

  async download() {
    await request({
      uri: 'http://localhost/download/image.jpg',
      jar: this.cookie
    })
    .then(b => console.log(b))
    .catch(e => console.error(e))
  }

  query() {
    // ...
  }
}

const downloader = new ImageDownloader
downloader.download()
Run Code Online (Sandbox Code Playgroud)

它返回给我,我需要登录(服务器响应) ...但如果我做这个改变它是有效的:

async download() {
  await init() // <<<<<<<<<<<<
  await request({
    uri: 'http://localhost/download/image.jpg',
    jar: this.cookie
  })
  .then(b => console.log(b))
  .catch(e => console.error(e))
}
Run Code Online (Sandbox Code Playgroud)

它只是如果我叫工作initdownload方法.

如果我把console.log(this.cookie)download它返回一个空的CookieJar,如果我把同样的init它会返回正确的Cookie,但它出现下载的执行甚至寿我把它叫做在构造函数调用之前download.

怎么解决?非常感谢你.

@编辑

我做了@ agm1984@Jaromanda X告诉我的更改,但它仍然无效:(

const request = require('request-promise-native')

class ImageDownloader {
  constructor(username = null, password = null) {
    this.username = username
    this.password = password
    this.cookie = request.jar()

    this.init().catch(e => console.error(e))
  }

  async init() {
    return await request({
      uri: 'http://localhost/login',
      jar: this.cookie,
      method: 'post',
      formData: {
        'username': 'admin',
        'password': 'admin'
      }
    })
  }

  async download() {
    return await request({
      uri: 'http://localhost/download/image.jpg',
      jar: this.cookie
    })
  }

  query() {
    // ...
  }
}

const downloader = new ImageDownloader
downloader.download()
          .then(b => console.log(b))
          .catch(e => console.error(e))
Run Code Online (Sandbox Code Playgroud)

但话说再说......除非我打电话给init内线,否则它不起作用download.

小智 2

这里的问题是init异步的。像这样使用它:

const downloader = new ImageDownloader;
downloader.download();
Run Code Online (Sandbox Code Playgroud)

download函数正在执行,但init尚未完成。

我不会在构造函数中调用 init 方法。我要做的是这样的:

1-从构造函数中删除 init 调用。
2-使用这样的类:

const downloader = new ImageDownloader();
downloader.init()
  .then(() => downloader.download());
Run Code Online (Sandbox Code Playgroud)

如果你在函数中调用 init ,async你可以这样做:

await downloader.init();
const result = await downloader.download();
Run Code Online (Sandbox Code Playgroud)