[英]How to deal with returned object on Error in a Promise-based business-level function in Node.js?
I need to create a business level function called "getLocationById" which retrieves some data from a remote server via REST API. 我需要创建一个名为“ getLocationById”的业务级别功能,该功能通过REST API从远程服务器中检索一些数据。 This function is then called by a router to display the data on a web page. 然后,路由器会调用此功能以在网页上显示数据。
If the fetch call is successful, the json result is returned as Promise. 如果获取调用成功,则json结果作为Promise返回。 However, what should be returned to the router if fetch caught an error, eg remote server was not responding or responding with a 500 error? 但是,如果抓取出现错误(例如,远程服务器未响应或响应500错误),应返回路由器什么?
Furthermore, how does the route respond to the error? 此外,路由如何响应错误?
const fetch = require('node-fetch');
const p_conf = require('../parse_config'); // Configuration
const db = {
getLocationById: function(locId) {
fetch(`${p_conf.SERVER_URL}/parse` + '/classes/location', { method: 'GET', headers: {
'X-Parse-Application-Id': p_conf.APP_ID,
'X-Parse-REST-API-Key': p_conf.REST_API_KEY
}})
.then(res1 => return res1.json()) // RETURN A PROMISE ON SUCCESS
.catch((error) => {
console.log(error);
**WHAT TO RETURN TO THE ROUTER ON ERROR HERE?**
});
}
};
EDIT: 编辑:
const db_location = {
getLocations: function() {
//res.send("respond with 'locations' router.");
fetch(`${p_conf.SERVER_URL}/parse` + '/classes/GCUR_LOCATION', { method: 'GET', headers: {
'X-Parse-Application-Id': p_conf.APP_ID,
'X-Parse-REST-API-Key': p_conf.REST_API_KEY
}})
.then(res1 => res1)
.catch((error) => {
console.log(error);
return Promise.reject(new Error(error));
})
}
};
In router: 在路由器中:
router.get('/', function(req, res, next) {
db_location.getLocations()
.then(r => res.send(r.json())) // WHERE AN ERROR WAS THROWN
.catch((err) => {
console.log(err);
return next(err);
})
});
The following error was thrown: 引发以下错误:
TypeError: Cannot read property 'then' of undefined
on .then(r => res.send(r.json()))
在.then(r => res.send(r.json()))
上.then(r => res.send(r.json()))
FURTHER EDITS: 进一步编辑:
I then made the following changes. 然后,我进行了以下更改。
business layer 业务层
getLocations: function() {
// According to node-fetch documentation, fetch returns a Promise object.
return fetch(`${p_conf.SERVER_URL}/parse` + '/classes/GCUR_LOCATION', { method: 'GET', headers: {
'X-Parse-Application-Id': p_conf.APP_ID,
'X-Parse-REST-API-Key': p_conf.REST_API_KEY
} });
}
Router side: 路由器端:
router.get('/', function(req, res, next) {
db_location.getLocations()
.then(r => {
console.log("r.json(): " + r.json());
res.send(r.json())})
.catch((err) => {
console.log(err);
return next(err);
})
});
Then a new error was thrown: 然后引发了一个新的错误:
(node:10184) UnhandledPromiseRejectionWarning: TypeError: body used already for: http://localhost:1337/parse/classes/GCU
R_LOCATION
at Response.consumeBody (C:\Work\tmp\node_modules\node-fetch\lib\index.js:326:30)
at Response.json (C:\Work\tmp\node_modules\node-fetch\lib\index.js:250:22)
at db_location.getLocations.then.r (C:\Work\tmp\ExpressApps\express-parse-server\routes\locations.js:30:13)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:228:7)
(node:10184) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing ins
ide of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejectio
n id: 5)
(node:10184) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejection
s that are not handled will terminate the Node.js process with a non-zero exit code.
I believed the fetch function returned a Promise object that can be received by the calling function from the route? 我相信fetch函数返回的Promise对象可以由调用函数从路由接收到吗?
On failure or error, the system needs to do the following: 在发生故障或错误时,系统需要执行以下操作:
Operational errors can be ignored by 操作错误可以被忽略
In case of server no connecting, the system should retry after an interval of 60 seconds 如果服务器未连接,则系统应在60秒的间隔后重试
Programming errors: 编程错误:
If your error needs to be handled by the router you either need to not catch()
in getLocationById
or catch()
there, process what you need, and then return Promise.reject(error)
so the router can still take care of it downstream. 如果需要通过你要么需要不是路由器处理您的错误catch()
在getLocationById
或catch()
那里,过程你需要什么,然后返回Promise.reject(error)
所以路由器仍然可以照顾它下游。
Something like: 就像是:
function getLocation() { return Promise.reject('some error') // fake fetch error .then(r => r ) .catch(error => { console.log("handling error in getlocation") // maybe logging or other functions return Promise.reject(error) }) } // in routes: getLocation() .then(r => console.log("sending to user")) .catch(error => console.log("sending error to user: ", error))
If you don't have process the error in getLocation()
just don't catch it and the error will go down the chain: 如果您没有处理getLocation()
中的错误,那就不要抓住它,该错误将沿链式进行:
function getLocation() { return Promise.reject('some error') .then(r => r ) } // in routes: getLocation() .then(r => console.log("sending to user")) .catch(error => console.log("sending error to user: ", error))
Your new edits are close! 您的新修改已接近! First let's clear up a misconception you have about fetch . 首先,让我们澄清一下您对fetch的误解。 Non-OK responses do not result in the fetch promise being rejected. 非OK响应不会导致获取承诺被拒绝。 In order to determine if a call has a successful response, check response.ok . 为了确定呼叫是否有成功的响应,请检查response.ok 。
Next we need to investigate the json
method. 接下来,我们需要研究json
方法。 Looking at the documentation we see that it also returns a promise and not JSON. 查看文档,我们看到它还返回一个promise而不是JSON。
Here's a version of your router that's a closer to what you're looking for: 这是您的路由器的一个版本,它更接近您要寻找的版本:
router.get('/', function(req, res, next) {
db_location.getLocations()
.then(r => {
if (r.ok) { return r.json(); }
throw 'Something went wrong!';
})
.then(data => res.json(data))
.catch((err) => {
console.log(err);
next(err);
})
});
I think it's great that you're learning promises. 我认为您正在学习承诺真是太好了。 Once you feel comfortable with promises check out async/await . 一旦您对诺言感到满意,请退出async / await 。 It'll make your code easier to read but having an understanding of promises is important. 这将使您的代码更易于阅读,但是了解诺言很重要。
Try switching to the following code and let me know if it works: 尝试切换到以下代码,让我知道它是否有效:
router.get('/', function(req, res, next) {
return db_location.getLocations().then(r => {
console.log("r.json(): " + r.json());
return res.json(r);
})
.catch(err => {
console.log(err);
return next(err);
})
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.