如何正确重新抛出 http req.on(‘error’, (error) => {} error?

huangapple go评论105阅读模式
英文:

How to I properly re-throw http req.on('error', (error) => {} error?

问题

以下是您要翻译的部分:

"I'm setting up a little Kubernetes Job to upload a repair catalog to my server in an AKS cluster using an endpoint, basically it will just execute the uploadRepairCatalog() javascript function at startup.

Inside the try block of uploadRepairCatalog() function I first call createFirebaseUser() which creates the authToken needed by the server endpoint. Then I call sendRepairData() which inside a loop makes the http calls to the endpoint and they both throw. If any error is thrown by the previous two functions, inside uploadRepairCatalog()'s catch (error) block I call deleteRepairs() which delete whatever sendRepairData() eventually managed to save in the db before throwing an error, and I re-throw the error so the container fails and it all restarts. At last insight the finally block I call deleteFirebaseUser() to cleanup Firebase from the initially created user. As I'm running the code locally sendRepairData() always throws as it doesn't connect to the server. I'm expecting the deleteFirebaseUser() to be called every time uploadRepairCatalog() enters the finally block but whenever an error is thrown by sendRepairData() it isn't called, so user isn't deleted. If I start the code again then createFirebaseUser() throws as the user already exists, but then it finally does run deleteFirebaseUser().

Trying to debugging it I saw that the problem is that I'm trying to re-throw the error from req.on('error', (error) => {} but then it's not caught by sendRepairData() catch block, hence is not re-thrown to be caught by uploadRepairCatalog() catch block. I confirmed it by trowing a general Error instead of re-throwing req.on('error', (error) => {} error and with that it all works as expected.

How to I properly re-throw req.on('error', (error) => {} error?"

请注意,我已将代码部分从翻译中排除。如果您需要关于代码的任何帮助,请随时提出具体问题。

英文:

I'm setting up a little Kubernetes Job to upload a repair catalog to my server in an AKS cluster using an endpoint, basically it will just execute the uploadRepairCatalog() javascript function at startup.

Inside the try block of uploadRepairCatalog() function I first call
createFirebaseUser() which creates the authToken needed by the server endpoint.
Then I call sendRepairData() which inside a loop makes the http calls to the endpoint and they both throw.
If any error is thrown by the previous two functions, inside uploadRepairCatalog()'s catch (error) block I call deleteRepairs() which delete whatever sendRepairData() eventually managed to save in the db before throwing an error, and I re-throw the error so the container fails and it all restarts.
At last insight the finally block I call deleteFirebaseUser() to cleanup Firebase from the initially created user.
As I'm running the code locally sendRepairData() always throws as it doesn't connect to the server.
I'm expecting the deleteFirebaseUser() to be called every time uploadRepairCatalog() enters the finally block but whenever an error is thrown by sendRepairData() it isn't called, so user isn't deleted.
If I start the code again then createFirebaseUser() throws as the user already exists, but then it finally does run deleteFirebaseUser().

Trying to debugging it I saw that the problem is that I'm trying to re-throw the error from sendRepairData()'s req.on('error', (error) => {} but then it's not caught by sendRepairData() catch block, hence is not re-thrown to be caught by uploadRepairCatalog() catch block. I confirmed it by trowing a general Error instead of re-throwing req.on('error', (error) => {} error and with that it all works as expected.

How to I properly re-throw req.on('error', (error) => {} error?

async function sendRepairData() {
  // Read the catalog JSON file
  try {
    const catalogData = fs.readFileSync('catalog.json'); 
    const catalog = JSON.parse(catalogData);

    // Access the repairs array from the catalog
    repairs = catalog.repairs;
    console.log('expected repairs to send: ', repairs.length);

    for (const repair of repairs) {
      const options = {
        host: host,
        port: port,
        path: path,
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          AuthToken: authToken,
          apikey: apiKey,
        },
      };

      const req = http.request(options, (res) => {
        let data = '';

        res.on('data', (chunk) => {
          data += chunk;
        });

        res.on('end', () => {
          console.log('Response:', data);
          // save response data for resetting the db in case of error
          savedRepairs.push(JSON.parse(data));
        });
      });

      req.on('error', (error) => {
        console.log('sendRepairData() http request error:', error);
        throw error; // this should get caught by the catch block to be re-thrown but it doesn't.
        // throw Error(`${error.name}, ${error.message}, ${error.stack}`);
      });

      req.write(JSON.stringify(repair));
      req.end();
      // throw Error('test error from sendRepairData()'); // throwing this error works
    } 
  } catch (error) {
    console.error('\n\nsendRepairData() catch\n\nerror :', error);
    throw error;
  } 
}

答案1

得分: 1

以下是您的代码的中文翻译:

我会将您的代码拆分成多个函数

async function getData() {
    const data = await fs.readFileSync("catalog.json");
    const catalog = JSON.parse(data);
    return catalog.repairs;
}

async function sendRepair(repair, options) {
    return new Promise((resolve, reject) => {
        const req = http.request(options, (res) => {
            let data = "";
            res.on("data", (chunk) => (data += chunk));
            res.on("end", () => resolve(JSON.parse(data)));
        });
        req.on("error", reject);
        req.end(JSON.stringify(repair));
    });
}

async function sendRepairs(repairs) {
    const options = {
        host,
        port,
        path,
        method: "POST",
        headers: {
            "Content-Type": "application/json",
            AuthToken: authToken,
            apikey: apiKey,
        },
    };
    await Promise.all(repairs.map((repair) => sendRepair(repair, options)));
}

由于HTTP请求现在包装在一个Promise中,您可以像这样协调所有操作:

const repairs = await getData();
try {
  await sendRepairs();
} catch(error) {
  // 处理错误
}

我还建议尝试使用node-fetch而不是原生的HTTP包,以简化您的工作。


<details>
<summary>英文:</summary>

I would split your code in multiple functions:

```js
async function getData() {
    const data = await fs.readFileSync(&quot;catalog.json&quot;);
    const catalog = JSON.parse(data);
    return catalog.repairs;
}

async function sendRepair(repair, options) {
    return new Promise((resolve, reject) =&gt; {
        const req = http.request(options, (res) =&gt; {
            let data = &quot;&quot;;
            res.on(&quot;data&quot;, (chunk) =&gt; (data += chunk));
            res.on(&quot;end&quot;, () =&gt; resolve(JSON.parse(data)));
        });
        req.on(&quot;error&quot;, reject);
        req.end(JSON.stringify(repair));
    });
}

async function sendRepairs(repairs) {
    const options = {
        host,
        port,
        path,
        method: &quot;POST&quot;,
        headers: {
            &quot;Content-Type&quot;: &quot;application/json&quot;,
            AuthToken: authToken,
            apikey: apiKey,
        },
    };
    await Promise.all(repairs.map((repair) =&gt; sendRepair(repair, options)));
}

Since the HTTP request is now wrapped in a Promise, you can orchestrate everything as:

const repairs = await getData();
try {
  await sendRepairs();
} catch(error) {
  // handle the error somehow
}

I would also try node-fetch instead of the native HTTP package, to make your life easier.

huangapple
  • 本文由 发表于 2023年6月1日 00:05:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76375410.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定