2016-11-30 172 views
2

我试图通过扩展默认构建自定义Angular 2 http请求,我使用Ionic 2本地存储来存储身份验证令牌。 (将来可能会使用文件系统)。我的问题是如何从我的http服务返回已解决的承诺,以便我可以订阅我的组件中的Observable。我试过Observable.fromPromise和其他变化无济于事。从承诺内部返回解决Observable

request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> { 

    // Get the token used for this request. 
    // * Need to return this promise resolved. 
    var promise = this.storage.get('token').then(token => { 

    if (typeof url === 'string') { // meaning we have to add the token to the options, not in url 
     if (!options) { 
     // let's make option object 
     options = {headers: new Headers()}; 
     } 
     options.headers.set('Authorization', 'Basic ' + token); 
    } else { 
    // we have to add the token to the url object 
     url.headers.set('Authorization', 'Basic ' + token); 
    } 

    return super.request(url, options).catch(this.catchAuthError(this)); 

    }).catch(error => { 
    console.log(error); 
    }); 

} 

想法基于此博客文章,但离子存储返回承诺。 http://www.adonespitogo.com/articles/angular-2-extending-http-provider/

+0

谁是'user'? –

+0

应该是令牌。 –

+1

在'then'中处理observable是不方便的。我猜它应该像'return Observable.fromPromise(this.storage.get('token'))。map(token => {...; return url})。mergeMap(url => super.request(。 ..))' – estus

回答

6

我不知道这是否存储返回一个承诺是其中Rx兼容,但如果它是那么的解决方案应该是这样的:

request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> { 

    return Observable 
     .fromPromise(this.storage.get('token')) 
     .flatMap(token => { 

      if (typeof url === 'string') { // meaning we have to add the token to the options, not in url 
       if (!options) { 
        // let's make option object 
        options = {headers: new Headers()}; 
       } 
       options.headers.set('Authorization', 'Basic ' + token); 
      } else { 
       // we have to add the token to the url object 
       url.headers.set('Authorization', 'Basic ' + token); 
      } 

      return super.request(url, options).catch(this.catchAuthError(this)); 

     }); 
    }); 

} 

如果承诺不兼容观测还是有一种方式来做到这一点,尽管它并不是那么优雅:

request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> { 

    return Observable.create((observer: Observer) => { 

     this.storage.get('token').then(token => { 

      if (typeof url === 'string') { // meaning we have to add the token to the options, not in url 
       if (!options) { 
        // let's make option object 
        options = {headers: new Headers()}; 
       } 
       options.headers.set('Authorization', 'Basic ' + token); 
      } else { 
       // we have to add the token to the url object 
       url.headers.set('Authorization', 'Basic ' + token); 
      } 

      super.request(url, options).catch(this.catchAuthError(this)).subscribe(result => { 
       observer.next(result); 
       observer.complete(); 
      }); 

     }).catch(error => { 
      observer.error(error); 
     }); 

    }); 

} 
+0

第一个选项奏效,谢谢!我之前没有使用flatmap。还需要添加导入'rxjs/add/operator/mergemap';让flatmap工作。 –