2015-04-06 23 views
43

Tôi có API HTTP trả về dữ liệu JSON cả về thành công và lỗi.tìm nạp: Từ chối lời hứa với đối tượng lỗi JSON

Một ví dụ thất bại sẽ trông như thế này:

~ ◆ http get http://localhost:5000/api/isbn/2266202022 
HTTP/1.1 400 BAD REQUEST 
Content-Length: 171 
Content-Type: application/json 
Server: TornadoServer/4.0 

{ 
    "message": "There was an issue with at least some of the supplied values.", 
    "payload": { 
     "isbn": "Could not find match for ISBN." 
    }, 
    "type": "validation" 
} 

Những gì tôi muốn đạt được trong mã JavaScript tôi một cái gì đó như thế này là:

fetch(url) 
    .then((resp) => { 
    if (resp.status >= 200 && resp.status < 300) { 
     return resp.json(); 
    } else { 
     // This does not work, since the Promise returned by `json()` is never fulfilled 
     return Promise.reject(resp.json()); 
    } 
    }) 
    .catch((error) => { 
    // Do something with the error object 
    } 
+0

Bạn có nghĩa là 'phương pháp json' trả về một' Promise'? – thefourtheye

+2

Có, theo thông số 'fetch' từ nhóm làm việc: https://fetch.spec.whatwg.org/#concept-body-consume-body – jbaiter

Trả lời

71
// This does not work, since the Promise returned by `json()` is never fulfilled 
return Promise.reject(resp.json()); 

Vâng, resp.json lời hứa sẽ được hoàn thành, chỉ Promise.reject không chờ đợi và từ chối ngay với lời hứa.

tôi sẽ cho rằng bạn chứ không phải muốn làm như sau:

fetch(url).then((resp) => { 
    let json = resp.json(); // there's always a body 
    if (resp.status >= 200 && resp.status < 300) { 
    return json; 
    } else { 
    return json.then(Promise.reject.bind(Promise)); 
    } 
}) 

(hoặc, được viết một cách rõ ràng)

return json.then(err => {throw err;}); 
+0

Cảm ơn, điều đó (hầu như) đã hoạt động! Tôi đã phải bọc Promise.reject trong một chức năng vô danh hoặc tôi nhận được một 'undefined không phải là một chức năng' lỗi, nhưng với sự thay đổi nhỏ nó hoạt động :-) – jbaiter

+0

Uh, bạn có lười biếng tải một shim Promise? Bản gốc 'Promise.reject' sẽ không bao giờ là' undefined'. – Bergi

+0

Lệnh tạm dừng được tải khi khởi động ứng dụng, vì vậy nó không nên tải xuống. Tôi có thể truy cập 'Promise.reject' cũng tốt từ trình gỡ lỗi. Đây là dấu vết đầy đủ: 'TypeError: undefined không phải là một hàm {stack:" TypeError: undefined không phải là một function↵ tại từ chối (native) ", message:" undefined không phải là một hàm "}' – jbaiter

26

Dưới đây là một cách tiếp cận hơi sạch dựa trên response.ok và tận dụng dữ liệu JSON cơ bản thay vì Promise được trả lại bởi .json().

function myFetchWrapper(url) { 
 
    return fetch(url).then(response => { 
 
    return response.json().then(json => { 
 
     return response.ok ? json : Promise.reject(json); 
 
    }); 
 
    }); 
 
} 
 

 
// This should trigger the .then() with the JSON response, 
 
// since the response is an HTTP 200. 
 
myFetchWrapper('http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY').then(console.log.bind(console)); 
 

 
// This should trigger the .catch() with the JSON response, 
 
// since the response is an HTTP 400. 
 
myFetchWrapper('https://content.googleapis.com/youtube/v3/search').catch(console.warn.bind(console));

+1

Ah, '.ok' trông thú vị. Tuy nhiên, tôi không thấy việc sử dụng" dữ liệu JSON cơ bản "là sạch hơn. Sau khi tất cả, bạn có thể đơn giản hóa việc này thành' fetch (url) .then (response = > response.ok? response.json(): response.json(). sau đó (err => Promise.reject (err))) ' – Bergi

+0

Tôi có nghĩa là thay vì' let json = resp.json(); 'where' json' là 'Promise', nó có thể đơn giản hơn để giải quyết' Promise' trước và sau đó sử dụng dữ liệu đã được giải quyết. Hoặc là phương thức tiếp cận hoạt động –

+0

Đã cố gắng từ chối lời hứa lồng nhau nhưng không hoàn toàn chắc chắn như thế nào. Hóa ra nó chỉ đơn giản là một cuộc gọi đến phương thức "từ chối" tĩnh. Một câu trả lời tốt hơn nhiều so với phương thức được chấp nhận trong quan điểm của tôi. – Andris

Các vấn đề liên quan