2

我需要创建一个名为“getLocationById”的业务级函数,它通过 REST API 从远程服务器检索一些数据。然后由路由器调用此函数以在网页上显示数据。

如果 fetch 调用成功,则 json 结果作为 Promise 返回。但是,如果 fetch 发现错误,例如远程服务器没有响应或响应 500 错误,应该向路由器返回什么?

此外,路由如何响应错误?

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

.then(r => res.send(r.json()))

进一步编辑:

然后我做了以下更改。

业务层

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);
  })  
});

然后抛出了一个新错误:

(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.

我相信 fetch 函数返回了一个 Promise 对象,调用函数可以从路由中接收该对象?

4

4 回答 4

1

您的新编辑已完成!首先让我们澄清一下您对fetch的误解。非 OK 响应不会导致 fetch Promise 被拒绝。为了确定呼叫是否有成功响应,请检查response.ok

接下来我们需要研究这个json方法。查看文档,我们看到它还返回一个 Promise 而不是 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);
    })  
});

我认为你正在学习承诺很棒。一旦您对 Promise 感到满意,请查看async/await。它会让你的代码更容易阅读,但理解 Promise 很重要。

于 2018-07-23T05:14:39.003 回答
0

在失败或错误时,系统需要执行以下操作:

  1. 注册错误
  2. 确定错误类型
  3. 操作错误,例如无法连接到服务器
  4. 程序员错误,这是错误,需要由开发人员修复

操作错误可以忽略

  1. 单元测试
  2. 处理异步和同步调用
  3. 确保所有参数都没有传递给函数
  4. 检查空参数,如果为 false,则显示错误,要求用户提供必填字段

如果服务器没有连接,系统应在 60 秒间隔后重试

编程错误:

  • 用 'throw' 终止函数</li>
  • 记录错误
  • 向用户显示适当的消息,而不使用任何技术术语
于 2018-07-18T00:27:36.033 回答
0

如果你的错误需要由路由器处理,你要么不在catch()getLocationById要么不在catch()那里,处理你需要的东西,然后返回Promise.reject(error),这样路由器仍然可以在下游处理它。

就像是:

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)) 

如果您没有处理错误,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))

于 2018-07-18T00:36:17.233 回答
0

尝试切换到以下代码并让我知道它是否有效:

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);
   })  
});
于 2018-07-23T05:34:13.817 回答