15

I have a tslint problem when I try to manage the result of an XMLHttpRequest call I do to upload files. Here is my current method I found on the internet :

// Files upload request
makeFileRequest(url: string, files: Array<File>) {
    return new Promise((resolve, reject) => {
        let formData: any = new FormData()
        let xhr = new XMLHttpRequest()
        for(let file of files) {
            formData.append("uploads[]", file, file.name)
        }
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    resolve(JSON.parse(xhr.response))
                } else {
                    reject(xhr.response)
                }
            }
        }
        xhr.open("POST", url, true)
        xhr.send(formData)
    })
}

So it works, the files are being uploaded and the backend replies a 200 response. But in the method where I use this function, I do this :

        this.makeFileRequest("theurl", this.listFiles)
        .map(res => res.json())
            .subscribe(
                res => console.log(res),
                error => console.log("fails")
            )

But tslint tells me this for at the map point :

TS2339 Property 'map' does not exist on type 'Promise<{}>'.

So I think it would be better to manage the makeFileRequest function so it returns an Observable instead of a Promise. And just in case, note I import "rxjs/add/operator/map".

Has anyone any idea ? Thanks !

Guigui
  • 641
  • 4
  • 8
  • 23

2 Answers2

24

map is a method of Observable, not Promise. Returning an Observable will fix the error:

makeFileRequest(url: string, files: Array<File>) {
    return Observable.fromPromise(new Promise((resolve, reject) => {
        let formData: any = new FormData()
        let xhr = new XMLHttpRequest()
        for (let file of files) {
            formData.append("uploads[]", file, file.name)
        }
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    resolve(JSON.parse(xhr.response))
                } else {
                    reject(xhr.response)
                }
            }
        }
        xhr.open("POST", url, true)
        xhr.send(formData)
    }));
}

The solution for the error:

Property 'json' does not exist on type '{}'

https://stackoverflow.com/a/33919897

Don't forget to import Response:

import {Response} from '@angular/http';
Community
  • 1
  • 1
Andrei Zhytkevich
  • 8,039
  • 2
  • 31
  • 45
  • Thanks, it works to do what I've asked :) Now I still have an issue by having a `Property 'json' does not exist on type '{}'` at the .map line, but that's another problem :( But that's weird, I do this at other Observable mapping instruction – Guigui Jun 10 '16 at 14:37
  • `json()` is a method from Response, since normally in http the Observable returns a Response object. – Ed Morales Jun 10 '16 at 16:15
  • I got this error: Failed to execute open on XMLHttpRequest: Invalid URL I'm using angular 2, can you help me? I'm pretty sure it is not the URL, but I'm new with angular 2 – Marlaurita Feb 25 '17 at 20:03
  • 1
    @MariLuna, it's hard to tell, what the problem is without seeing the code. Sounds like your url is not correct. – Andrei Zhytkevich Feb 27 '17 at 12:37
  • @AndreiZhytkevich Thank u, that was the problem, I wasn't putting the "http" – Marlaurita Feb 27 '17 at 16:20
  • For those that find this answer and are using Angular 8+ and RxJS 6+. See this Q&A: https://stackoverflow.com/questions/45784825/frompromise-does-not-exist-on-type-observable that you'll use `return from(...)` instead of `return Observable.fromPromise(...)` – kydreth Aug 14 '21 at 17:07
0

The simple way to achieve:

xhrCall(url, formData, header) {
    return Observable.create(function (observer) {
      let xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
          if (xhr.status == 200) {
            observer.next(xhr);
          } else {
            observer.error(xhr);
          }
        }
      };

      xhr.open("POST", url, true);
      xhr.setRequestHeader(header.name, header.value);
      xhr.send(formData);
    });
}
Sahil Ralkar
  • 2,331
  • 23
  • 25