【问题标题】:Chaining promises to cope with asynchronous promise from a this.storage.get() call链接承诺以处理来自 this.storage.get() 调用的异步承诺
【发布时间】:2017-01-22 18:39:49
【问题描述】:

我正在努力处理从我的应用程序的本地存储中异步检索数据,该应用程序是用 Angular2/ionic2 编写的。

我的代码如下:

  request(args) {
    var headers = new Headers();
    headers.append('Content-Type', 'application/json');

    // Retrieve the token from the local storage, if available
    this.storage.get('token').then((value) => {
      headers.append('Authorization', 'Token ' + value);
    });

    args = args || {};

    var url = this.API_URL + args.url;
    var method = args.method;
    var data = args.data || {};

    var options = new RequestOptions({headers: headers, withCredentials: this.use_session});

    return new Promise((resolve,reject) => {

      if (method == 'GET') {
        this.http.get(url, options)
          .map(res => res.text())
          .subscribe(
            (data:any) => {
              resolve(data);
            },
            (err:any) => {
              data = {};
              data['status'] = 0;
              data['non_field_errors'] = ["Could not connect to server. Please try again."];
              data['error'] = err;
              reject();
            },
            () => {
            }
          );
      }
    });
  }

调用请求函数的代码如下:

  authenticationStatus(){
    return this.request({
        'method': "GET",
        'url': "/user/"
      })
      .then((data:any) => {
          console.log('****** authenticationStatus: GET /user/ SUCCESS');
      });
  }

这又是这样调用的:

      this.djangoAuth.authenticationStatus()
        .then((data:any) => {
            this.loggedIn = true;
            this.enableMenu(true);
            this.root = PhotoPage;
          },
          (err:any)=>{
            this.loggedIn = false;
            this.enableMenu(false);
            this.root = LoginPage;
          });

我很难理解嵌套的 Promise,并且无法弄清楚如何修改上面的代码,以便 this.storage.get("token") 调用的结果在下面的代码中使用之前将数据添加到标题中。我认为我需要以某种方式链接承诺,但无法确定具体如何。

【问题讨论】:

  • 本地 localStorage 访问是同步的...不知道为什么你的被包装在一个承诺中
  • 这不是原生的,它是 angularjs/ionic
  • 都是使用原生javascript的框架
  • 是的,但是他们的本地存储版本使用了 Promise,而我正在使用的是他们的版本

标签: angularjs asynchronous typescript


【解决方案1】:

是的,您需要链接两个 Promise - 这实际上很容易。您所要做的就是从您传递给第一个承诺then() 方法的回调中返回第二个承诺。

您可以像这样重写您的代码(我将添加标头的代码移动到单独的函数中 - 我认为这样更具可读性)

// returns a promise that resolves to headers
createHeaders() {
  var headers = new Headers();
  headers.append('Content-Type', 'application/json');

  // Retrieve the token from the local storage, if available
  return this.storage.get('token').then((value) => {
    headers.append('Authorization', 'Token ' + value);
    return headers;
  });
}

request(args) {

  return this.createHeaders().then(headers => {
    args = args || {};

    var url = this.API_URL + args.url;
    var method = args.method;
    var data = args.data || {};

    var options = new RequestOptions({headers: headers, withCredentials: this.use_session});

    return new Promise((resolve,reject) => {

      if (method == 'GET') {
        this.http.get(url, options)
          .map(res => res.text())
          .subscribe(
            (data:any) => {
              resolve(data);
            },
            (err:any) => {
              data = {};
              data['status'] = 0;
              data['non_field_errors'] = ["Could not connect to server. Please try again."];
              data['error'] = err;
              reject();
            },
            () => {
            }
          );
      }
    });
  });
}

这一切中最困难的事情是不要忘记每一个必要的return。

另外,我注意到如果您的Promise 接收到除GET 以外的任何方法,则它永远不会完成 - 您可能希望在reject 中添加else 部分

if (method == 'GET') {
    ....
} else {
    reject(new Error('invalid method:' + method));
}

【讨论】:

  • args 的范围似乎存在问题。代码落在使用 args.url 和 args.method 的行上。
  • 我正在使用 Typescript 以防万一。
  • 是的,我忘了this。调用 createHeaders() 时需要它,回调内部也需要它(这就是我将 function 更改为 => 的原因)。固定。
猜你喜欢
  • 2020-06-10
  • 1970-01-01
  • 2017-05-30
  • 1970-01-01
  • 2017-04-17
  • 1970-01-01
  • 2016-09-03
  • 2019-02-21
  • 2018-04-10
相关资源
最近更新 更多