Angular2 Observables - 创建我自己的 - 订阅者undefined

时间:2016-05-23 08:52:50

标签: angularjs typescript angular rxjs

我无法确定这是一个范围问题还是我如何设置我的观察点的问题,但也许你可以提供帮助。

首先,我的逻辑。我的总体目标是能够在发送一个http.get请求之前检查一些数据是否保存在本地。我想做的是返回本地保存的数据(如果存在的话),我认为我可以使这个返回一个observable,这样我就可以订阅这个函数的输出,无论它是否返回本地数据或远程数据。任何关于这种逻辑的想法都将受到赞赏!

我正在关注More来实现我自己的观察。我遇到了一个问题,我无法在我的getData函数中定义我的观察者。

this blog post by Cory Rylan

Here is Cory's working demo - 您可以在日志中看到服务中的this._dataObserver未定义,而在Cory中则为@Component({ selector: 'my-app', template: ` <landing-page></landing-page> `, providers: [DataService], directives: [LandingPageComponent] }) export class App { constructor() { } } bootstrap(App, [HTTP_BINDINGS]) .catch(err => console.error(err)); 。这就是造成我问题的原因。

以下是代码中的代码段:

App.ts

@Component({
  selector: 'landing-page',
  template : `
    hello
  `,
})
export class LandingPageComponent implements OnInit{
  data : Observable<any[]>;
  constructor(
    private _dataService : DataService
  ) { }

  ngOnInit() {
    this.data = this._dataService.data$;
    this._dataService.getData();
  }
}

LandingPageComponent.ts

@Injectable()
export class DataService {

   data$ : Observable<any[]>; // data stream
   private _baseUrl: string;
   private _dataObserver : Observer<any[]>;
   private _dataStore : {
    data : any[]
   };

  constructor (
    private _http: Http
  ) {
    this._baseUrl  = 'http://56e05c3213da80110013eba3.mockapi.io/api';
    this.data$ =  new Observable(observer => this._todosObserver = observer).share();
    this._dataStore = { data: [] };
  }

  /** **************
  * Public functions
  *****************/

  getData () {
    this._http.get(`${this._baseUrl}/todos`)
      .map(data => data.json())
      .subscribe( data => {
      this._dataStore.data = data;
      console.log(this._dataObserver);   //<------ This is undefined for me!
      this._dataObserver.next(this.data);
    },
    error => {
      console.log('couldn\'t load data! ' + error );
    });

  }

}

的DataService

public class MockRestClient : RestClient
{
    public TestServer TestServer { get; set; }
    public MockRestClient(TestServer testServer)
    {
        TestServer = testServer;
    }

    public override IRestResponse Execute(IRestRequest request)
    {
        // TODO: Currently the test server is only doing GET requests via RestSharp

        HttpResponseMessage response = null;

        Parameter body = request.Parameters.FirstOrDefault(p => p.Type == ParameterType.RequestBody);
        HttpContent content;


        if (body != null)
        {
            object val = body.Value;
            byte[] requestBodyBytes;
            string requestBody;


            if (val is byte[])
            {
                requestBodyBytes = (byte[]) val;
                content = new ByteArrayContent(requestBodyBytes);
            }
            else
            {
                requestBody = Convert.ToString(body.Value);
                content = new StringContent(requestBody);
            }
        }
        else 
            content = new StringContent("");

        string urladd = "";

        IEnumerable<string> @params = from p in request.Parameters
            where p.Type == ParameterType.GetOrPost && p.Value != null
            select p.Name + "=" + p.Value;

        if(!@params.IsNullOrEmpty())
            urladd = "?" + String.Join("&", @params);


        IEnumerable<HttpHeader> headers = from p in request.Parameters
                                          where p.Type == ParameterType.HttpHeader
                                          select new HttpHeader
                                          {
                                              Name = p.Name,
                                              Value = Convert.ToString(p.Value)
                                          };

        foreach (HttpHeader header in headers)
        {
            content.Headers.Add(header.Name, header.Value);
        }

        content.Headers.ContentType.MediaType = "application/json";

        switch (request.Method)
        {
            case Method.GET:
                response = TestServer.HttpClient.GetAsync(request.Resource + urladd).Result;
                break;
            case Method.DELETE:
                response = TestServer.HttpClient.DeleteAsync(request.Resource + urladd).Result;
                break;
            case Method.POST:
                response = TestServer.HttpClient.PostAsync(request.Resource + urladd, content).Result;
                break;
            case Method.PUT:
                response = TestServer.HttpClient.PutAsync(request.Resource + urladd, content).Result;
                break;
            default:
                return null;
        }

        var restResponse = ConvertToRestResponse(request, response);
        return restResponse;
    }

    private static RestResponse ConvertToRestResponse(IRestRequest request, HttpResponseMessage httpResponse)
    {
        RestResponse restResponse1 = new RestResponse();
        restResponse1.Content = httpResponse.Content.ReadAsStringAsync().Result;
        restResponse1.ContentEncoding = httpResponse.Content.Headers.ContentEncoding.FirstOrDefault();
        restResponse1.ContentLength = (long)httpResponse.Content.Headers.ContentLength;
        restResponse1.ContentType = httpResponse.Content.Headers.ContentType.ToString();
        if (httpResponse.IsSuccessStatusCode == false)
        {
            restResponse1.ErrorException = new HttpRequestException();
            restResponse1.ErrorMessage = httpResponse.Content.ToString();
            restResponse1.ResponseStatus = ResponseStatus.Error;
        }
        restResponse1.RawBytes = httpResponse.Content.ReadAsByteArrayAsync().Result;
        restResponse1.ResponseUri = httpResponse.Headers.Location;
        restResponse1.Server = "http://localhost";
        restResponse1.StatusCode = httpResponse.StatusCode;
        restResponse1.StatusDescription = httpResponse.ReasonPhrase;
        restResponse1.Request = request;
        RestResponse restResponse2 = restResponse1;
        foreach (var httpHeader in httpResponse.Headers)
            restResponse2.Headers.Add(new Parameter()
            {
                Name = httpHeader.Key,
                Value = (object)httpHeader.Value,
                Type = ParameterType.HttpHeader
            });
        //foreach (var httpCookie in httpResponse.Content.)
        //    restResponse2.Cookies.Add(new RestResponseCookie()
        //    {
        //        Comment = httpCookie.Comment,
        //        CommentUri = httpCookie.CommentUri,
        //        Discard = httpCookie.Discard,
        //        Domain = httpCookie.Domain,
        //        Expired = httpCookie.Expired,
        //        Expires = httpCookie.Expires,
        //        HttpOnly = httpCookie.HttpOnly,
        //        Name = httpCookie.Name,
        //        Path = httpCookie.Path,
        //        Port = httpCookie.Port,
        //        Secure = httpCookie.Secure,
        //        TimeStamp = httpCookie.TimeStamp,
        //        Value = httpCookie.Value,
        //        Version = httpCookie.Version
        //    });
        return restResponse2;
    }

感谢您的任何想法

1 个答案:

答案 0 :(得分:3)

_dataObserver为空,因为您没有订阅关联的observable。不要忘记可观察者是懒惰的......

您可以尝试以下方法:

ngOnInit() {
  this.data = this._dataService.data$.subscribe(data => { // <-----
    console.log(data);
  });
  this._dataService.getData();
}

修改

此外,您的代码中存在拼写错误:

this.data$ =  new Observable(observer => this._todosObserver = observer).share();

您应该使用_dataObserver代替_todosObserver

this.data$ =  new Observable(observer => this._dataObserver = observer).share();