这就是我的目标:
import 'whatwg-fetch';
function fetchVehicle(id) {
return dispatch => {
return dispatch({
type: 'FETCH_VEHICLE',
payload: fetch(`http://swapi.co/api/vehicles/${id}/`)
.then(status)
.then(res => res.json())
.catch(error => {
throw(error);
})
});
};
}
function status(res) {
if (!res.ok) {
return Promise.reject()
}
return res;
}
编辑:承诺不会被拒绝,这就是我想要弄清楚的。
我在Redux中使用此fetch polyfill redux-promise-middleware。
答案 0 :(得分:68)
Fetch promise仅在发生网络错误时拒绝TypeError。由于4xx和5xx响应不是网络错误,因此无法捕获。您需要自己抛出错误才能使用Promise#catch
。
fetch Response方便地提供ok
,告诉您请求是否成功。这样的事情可以解决问题:
fetch(url).then((response) => {
if (response.ok) {
return response.json();
} else {
throw new Error('Something went wrong');
}
})
.then((responseJson) => {
// Do something with the response
})
.catch((error) => {
console.log(error)
});
答案 1 :(得分:8)
感谢大家的帮助,拒绝var mongodb = require('mongodb').MongoClient;
module.exports= {
establishConnection: function (connectionstring, databasename, queryby, queryval, callback) {
var filenames=[];
var filepaths=[];
var results;
mongodb.connect(connectionstring, function (err, db) {
if (callback) {
callback();
}
if (!err) {
var cursor=db.collection(databasename).find();
cursor.each(function(err,doc){
if(doc!=null) {
callback(doc.filename+","+doc.filepath);
}
})
}
else
console.log("Error happened");
});
},
addvalues: function (connectionstring, databasename, filename, filepath, callback) {
if (callback) {
callback();
}
mongodb.connect(connectionstring, function (err, db) {
var collec = db.collection(databasename);
if (collec != null) {
db.collection('storedimages').insert({
"filename": filename,
"filepath": filepath
}, {w: 1}, function (err, records) {
if (records != null) {
console.log("Record added");
db.close();
}
else
console.log("Cannot add");
});
}
else {
console.log("Database not found! error");
}
});
},
retrievevalues: function ( connectionstring, databasename, filename, filepath, callback) {
if (callback) {
callback();
}
mongodb.connect(connectionstring, function (err, db) {
var collec = db.collection(databasename);
if (collec != null) {
db.collection('storedimages').find({"filename":filename,"filepath":filepath},{w:1},function(err,records){
if(records!=null) {
console.log("Record retrieved");
db.close();
}
else
console.log("Cannot retrieve");
});
}
else {
console.log("Database not found! error");
}
});
}
}`
中的承诺解决了我的问题:
.catch()
答案 2 :(得分:6)
对我来说, fny的答案确实掌握了一切。由于fetch不会引发错误,因此我们需要自己引发/处理错误。 用异步/等待发布我的解决方案。我认为它更具前瞻性和可读性
解决方案1:不抛出错误,请自行处理错误
async _fetch(request) {
const fetchResult = await fetch(request); //Making the req
const result = await fetchResult.json(); // parsing the response
if (fetchResult.ok) {
return result; // return success object
}
const responseError = {
type: 'Error',
message: result.message || 'Something went wrong',
data: result.data || '',
code: result.code || '',
};
const error = new Error();
error.info = responseError;
return (error);
}
如果遇到错误,我们将构建一个错误对象,普通的JS对象并返回它,缺点是我们需要在外部进行处理。 使用方法:
const userSaved = await apiCall(data); // calling fetch
if (userSaved instanceof Error) {
debug.log('Failed saving user', userSaved); // handle error
return;
}
debug.log('Success saving user', userSaved); // handle success
解决方案2:使用try / catch
引发错误async _fetch(request) {
const fetchResult = await fetch(request);
const result = await fetchResult.json();
if (fetchResult.ok) {
return result;
}
const responseError = {
type: 'Error',
message: result.message || 'Something went wrong',
data: result.data || '',
code: result.code || '',
};
let error = new Error();
error = { ...error, ...responseError };
throw (error);
}
在这里,我们抛出并创建了我们创建的错误,因为Error ctor只批准字符串,Im创建了普通的Error js对象,其用途为:
try {
const userSaved = await apiCall(data); // calling fetch
debug.log('Success saving user', userSaved); // handle success
} catch (e) {
debug.log('Failed saving user', userSaved); // handle error
}
解决方案3:使用客户错误
async _fetch(request) {
const fetchResult = await fetch(request);
const result = await fetchResult.json();
if (fetchResult.ok) {
return result;
}
throw new ClassError(result.message, result.data, result.code);
}
并且:
class ClassError extends Error {
constructor(message = 'Something went wrong', data = '', code = '') {
super();
this.message = message;
this.data = data;
this.code = code;
}
}
希望有帮助。
答案 3 :(得分:2)
我刚检查了响应对象的状态:
$promise.then( function successCallback(response) {
console.log(response);
if( response.status === 200 ) { ... }
});
答案 4 :(得分:1)
我所做的是编写一个采用泛型的 fetch
包装器,如果 response
是 ok
,它将自动 .json()
并输入断言结果,否则包装器抛出 response
export const fetcher = async <T>(input: RequestInfo, init?: RequestInit) => {
const response = await fetch(input, init);
if (!response.ok) {
throw response;
}
return response.json() as Promise<T>;
};
然后我会捕捉错误并检查它们是否是 instanceof
Response
。这样 TypeScript 就知道 error
具有 Response
属性,例如 status
statusText
body
headers
等,我可以为每个属性应用自定义消息4xx
5xx
状态代码。
try {
return await fetcher<LoginResponse>("http://localhost:8080/login", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({ email: "user@example.com", password: "passw0rd" }),
});
} catch (error) {
if (error instanceof Response) {
switch (error.status) {
case 401:
throw new Error("Invalid login credentials");
/* ... */
default:
throw new Error(`Unknown server error occured: ${error.statusText}`);
}
}
throw new Error(`Something went wrong: ${error.message || error}`);
}
如果发生网络错误之类的事情,可以在 instanceof
Response
检查之外使用更通用的消息来捕获它,即
throw new Error(`Something went wrong: ${error.message || error}`);
答案 5 :(得分:0)
@fny 的答案(已接受的答案)对我不起作用。 throw new Error()
没有被 .catch
接收。我的解决方案是使用构建新承诺的函数包装 fetch
:
function my_fetch(url, args) {
return new Promise((resolve, reject) => {
fetch(url, args)
.then((response) => {
response.text().then((body) => {
if (response.ok) {
resolve(body)
} else {
reject(body)
}
})
})
.catch((error) => { reject(error) })
})
}
现在,.catch
方法将获取所有错误和非正常返回:
my_fetch(url, args)
.then((response) => {
// Do something with the response
})
.catch((error) => {
// Do something with the error
})