重试Node.js http.request(发布,发布,删除) [英] Retry nodejs http.request (post,put,delete)

查看:99
本文介绍了重试Node.js http.request(发布,发布,删除)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请在不使用Node.js中任何第三方模块的情况下,对错误/条件进行重试的正确方法是什么?

What is the correct way to implement a retry on error/condition without using any third party modules in nodejs, please?

我不确定如何针对错误调用相同的函数,以及如何将原始回调/数据传递给新调用的函数?

I'm not sure how to call the same function on the error and how to then pass the original callback/data to the newly called function?

我需要销毁/结束插座吗?

Do I need to destroy/end the sockets?

我尝试查找示例,但只找到了似乎无效的第三方模块和http.get示例的引用.一个如何测试呢? 我尝试以下操作均未成功:

I've tried looking for examples but have only found reference to third party modules and http.get samples which don't seem to work. How does one test this? I have attempted the below without success:

      async pingApi(cb) {
        let options = {
        "method":"post",
         "path": `/API/pingAPI?${this.auth}`, /ect do I reference this path?
          }
        };
        let request = await http.request(options, (response) => {
          let body = new Buffer(0);
          response.on('data', (chunk) => {
            body = Buffer.concat([body, chunk]);
          });
          response.on('end', function () {
            if (this.complete) {
              let decoded = new Buffer(body, 'base64').toString('utf8')
              let json = JSON.parse(decoded);
              if (json.result != 'OK') {
                setTimeout(pingApi, 1000); //cant pass callback
              } else {
                cb(null, json.result) //works
              }
            }
          });
        })
        request.end(); //does the socket need to be closed if retry is this function?
      }

向我指出正确的方向或批评的任何帮助将不胜感激,因为我认为这对我来说是非常重要的学习曲线.

Any help, pointing in the right direction or criticism will be greatly appreciated as I think this is a very important learning curve for me.

先谢谢您

推荐答案

我不确定如何针对错误调用相同的函数,以及如何将原始回调/数据传递给新调用的函数?

I'm not sure how to call the same function on the error and how to then pass the original callback/data to the newly called function?

我不确定您函数中的其他所有内容是否正确,但是您可以通过更改以下内容来修正您要查询的递归:

I don't know for sure that everything else in your function is correct, but you can fix the recursion that you're asking about by changing this:

setTimeout(pingApi, 1000); //cant pass callback

对此:

setTimeout(() => {
    this.pingApi(cb);
}, 1000);

这里没有显示整个上下文,但是如果pingApi()是一种方法,那么您还需要跟踪this值,以便可以调用this.pingApi(db).您可以使用以下箭头函数回调保留this的值:

You aren't showing the whole context here, but if pingApi() is a method, then you also need to keep track of the this value to you can call this.pingApi(db). You can preserve the value of this by using arrow function callbacks like this:

response.on('end', () => { ... });

我注意到这里还有其他东西:

Other things I notice that look off here:

  1. 没有理由使用await http.request(). http.request()不会返回承诺,因此将await与它一起使用不会做任何有用的事情.
  2. 没有await,就没有理由将您的函数声明为async,因为没有人使用它的返回承诺.
  3. 目前尚不清楚if (this.complete)是做什么的.由于这是在常规函数回调中,因此this的值将不是您的pingApi对象.您通常应该将this保存在范围内的更高位置,通常使用const self = this,或者所有内部回调都需要使用箭头功能,以便保留this的值.
  4. 您可能应该将try/catch放在JSON.parse()周围,因为如果输入不是完美的JSON,它可能会抛出.
  5. 您可能不应永远重试.服务器真的讨厌永远重试的客户端,因为如果出现问题,客户端可能会无限期地每秒刷新服务器.我建议一定数量的最大重试次数,然后放弃一个错误.
  1. There's no reason to use await http.request(). http.request() does not return a promise so using await with it does not do anything useful.
  2. Without the await, there's then no reason for your function to be declared async since nobody is using a returned promise from it.
  3. It's not clear what if (this.complete) is meant to do. Since this is inside a regular function callback, the value of this won't be your pingApi object. You should either save this higher in the scope typically with const self = this or all callbacks internally need to be arrow functions so the value of this is preserved.
  4. You should probably put try/catch around JSON.parse() because it can throw if the input is not perfect JSON.
  5. You should probably not retry forever. Servers really hate clients that retry forever because if something goes wrong, the client may just be bashing the server every second indefinitely. I'd suggest a certain number of max retries and then give up with an error.

我需要销毁/结束插座吗?

Do I need to destroy/end the sockets?

否,请求结束后会自动发生.

No, that will happen automatically after the request ends.

如何对此进行测试?

How does one test this?

您必须在服务器中创建一个测试路由,该测试路由会返回前几个请求的错误情况,然后返回成功的响应,并查看您的代码是否适用于此.

You have to create a test route in your server that returns the error condition for the first few requests and then returns a successful response and see if your code works with that.

这是尝试进行代码修复的步骤(未经测试):

Here's an attempt at a code fixup (untested):

const maxRetries = 10;

pingApi(cb, cnt = 0) {
    let options = {
    "method":"post",
     "path": `/API/pingAPI?${this.auth}`, // ect do I reference this path?
    };
    let request = http.request(options, (response) => {
      let body = new Buffer(0);
      response.on('data', (chunk) => {
        body = Buffer.concat([body, chunk]);
      });
      response.on('end', () => {
        if (this.complete) {
          let decoded = new Buffer(body, 'base64').toString('utf8')
          try {
            let json = JSON.parse(decoded);
            if (json.result != 'OK') {
                if (cnt < maxRetries)
                    setTimeout(() => {
                        this.pingApi(cb, ++cnt);
                    }, 1000);
                 } else {
                    cb(new Error("Exceeded maxRetries with error on pingApi()"));
                 }
            } else {
                cb(null, json.result) //works
            }
          } catch(e) {
              // illegal JSON encountered
              cb(e);
          }
        }
      });
    })
    request.end();
 }

有关此代码的尚待解决的问题:

Remaining open questions about this code:

  1. this.complete在做什么,应该引用什么this?
  2. 为什么没有request.write()发送POST请求的正文?
  1. What is this.complete doing and what this should it be referencing?
  2. Why is there no request.write() to send the body of the POST request?


我知道您不要求任何外部模块,但是我这样做的首选方法是使用Promise,并在http.request()周围使用请求-承诺包装器,因为它为您处理了很多此代码(检查响应.状态,为您解析JSON,使用Promise接口等).您可以看到代码更简洁:


I know you ask for no external modules, but my preferred way of doing this would be to use promises and to use the request-promise wrapper around http.request() because it handles a lot of this code for you (checks response.status for you, parses JSON for you, uses promise interface, etc...). You can see how much cleaner the code is:

const rp = require('request-promise');
const maxRetries = 5;

pingApi(cnt = 0) {
    let options = {
        method: "post",
        url: `http://somedomain.com/API/pingAPI?${this.auth}`, 
        json: true
    };
    return rp(options).then(result => {
        if (result.result === "OK") {
            return result;
        } else {
            throw "try again";  // advance to .catch handler
        }
    }).catch(err => {
        if (cnt < maxRetries) {
            return pingApi(++cnt);
        } else {
            throw new Error("pingApi failed after maxRetries")
        }
    });
}

然后,使用示例:

pingApi().then(result => {
    console.log(result);
}).catch(err => {
    console.log(err);
})

这篇关于重试Node.js http.request(发布,发布,删除)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆