Javascript 如何处理Node.js中基于承诺的业务级函数返回的对象出错?
我需要创建一个名为“getLocationById”的业务级函数,该函数通过RESTAPI从远程服务器检索一些数据。然后,路由器调用此函数以在网页上显示数据 如果fetch调用成功,json结果将作为Promise返回。但是,如果fetch发现错误,例如远程服务器没有响应或响应错误为500,则应向路由器返回什么 此外,路由如何响应错误Javascript 如何处理Node.js中基于承诺的业务级函数返回的对象出错?,javascript,node.js,express,promise,node-fetch,Javascript,Node.js,Express,Promise,Node Fetch,我需要创建一个名为“getLocationById”的业务级函数,该函数通过RESTAPI从远程服务器检索一些数据。然后,路由器调用此函数以在网页上显示数据 如果fetch调用成功,json结果将作为Promise返回。但是,如果fetch发现错误,例如远程服务器没有响应或响应错误为500,则应向路由器返回什么 此外,路由如何响应错误 const fetch = require('node-fetch'); const p_conf = require('../parse_config'
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?**
});
}
};
编辑:
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));
})
}
};
在路由器中:
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);
})
});
引发了以下错误:
TypeError: Cannot read property 'then' of undefined
(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.
然后(r=>res.send(r.json())
进一步编辑:
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));
})
}
};
然后我做了以下修改
业务层
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.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);
})
});
然后抛出一个新错误:
TypeError: Cannot read property 'then' of undefined
(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.
(节点:10184)未处理的PromisejectionWarning:TypeError:正文已用于:http://localhost:1337/parse/classes/GCU
R_位置
在Response.consumerbody(C:\Work\tmp\node\u modules\node fetch\lib\index.js:326:30)
在Response.json(C:\Work\tmp\node\u modules\node fetch\lib\index.js:250:22)
在db_location.getLocations.then.r(C:\Work\tmp\ExpressApps\expressparse server\routes\locations.js:30:13)
在
在进程中。_tickDomainCallback(internal/process/next_tick.js:228:7)
(节点:10184)未处理的PromisejectionWarning:未处理的承诺拒绝。此错误源于
没有catch块的异步函数的ide,或拒绝未使用.catch()处理的承诺。(拒绝
编号:5)
(节点:10184)[DEP0018]弃用警告:未处理的承诺拒绝已弃用。在未来,承诺拒绝
未处理的将使用非零退出代码终止Node.js进程。
我相信fetch函数返回了一个Promise对象,调用函数可以从路由接收到该对象?如果出现故障或错误,系统需要执行以下操作:
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));
})
}
};
- 用“throw”终止函数
- 记录错误
- 向用户显示适当的消息,而不使用任何技术术语
getLocationById
中不执行catch()
或在那里执行catch()
操作,处理您需要的内容,然后返回Promise.reject(error)
,这样路由器仍然可以在下游处理它
比如:
函数getLocation(){
return Promise.reject('some error')//fake fetch error
.然后(r=>r)
.catch(错误=>{
console.log(“getlocation中的处理错误”)//可能是日志或其他函数
返回承诺。拒绝(错误)
})
}
//路线:
getLocation()
.then(r=>console.log(“发送给用户”))
.catch(error=>console.log(“向用户发送错误:”,error))您的新编辑即将完成!首先,让我们澄清一个关于你的误解。非OK响应不会导致拒绝获取承诺。要确定呼叫是否有成功响应,请检查 接下来,我们需要研究该方法。查看文档,我们发现它还返回一个承诺,而不是JSON 这是一款更接近您所需的路由器版本:
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);
})
});
我认为你学习承诺是件好事。一旦你对承诺感到满意,就退房吧。这将使您的代码更易于阅读,但了解承诺很重要。尝试切换到以下代码,并告诉我它是否有效:
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);
})
});
如果出现错误,您希望发生什么?它应该向用户报告什么吗?@MarkMeyer是的,错误消息应该返回给路由器,然后路由器应该处理该消息并打印给前端用户。谢谢。但是在我修改后抛出了一个错误。请参阅我对该问题的编辑。@alextc您似乎没有从
getLocations()
返回任何内容。我想你需要Fetch()
的承诺。谢谢@Mark。我做了一些相关的改变。请参考进一步的编辑。函数返回“fetch”,它根据节点fetch文档返回一个Promise对象。