2016-11-30 84 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工作。 –