![](/img/trans.png)
[英]Invalid JSON Error at POST/PUT json with special characters using nodejs http.request()
[英]Retry nodejs http.request (post,put,delete)
在nodejs中不使用任何第三方模塊的情況下,實現對錯誤/條件重試的正確方法是什么?
我不確定如何針對錯誤調用相同的函數,以及如何將原始回調/數據傳遞給新調用的函數?
我需要銷毀/終止插座嗎?
我嘗試查找示例,但只發現了對第三方模塊和http.get示例的引用,這些似乎無效。 一個如何測試呢? 我嘗試以下操作均未成功:
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?
}
指出正確方向或提出批評的任何幫助將不勝感激,因為我認為這對我來說是非常重要的學習曲線。
先感謝您,
我不確定如何針對錯誤調用相同的函數,以及如何將原始回調/數據傳遞給新調用的函數?
我不確定函數中的其他所有內容是否正確,但是您可以通過更改以下內容來解決所要求的遞歸:
setTimeout(pingApi, 1000); //cant pass callback
對此:
setTimeout(() => {
this.pingApi(cb);
}, 1000);
您沒有在此處顯示整個上下文,但是如果pingApi()
是一種方法,則還需要跟蹤this
值,您可以調用this.pingApi(db)
。 您可以使用以下箭頭函數回調保留this
的值:
response.on('end', () => { ... });
我注意到的其他東西在這里看起來:
await http.request()
。 http.request()
不返回承諾,因此將await
與它一起使用不會做任何有用的事情。 await
,那么就沒有理由將您的函數聲明為async
因為沒有人使用它返回的promise。 if (this.complete)
應該做什么。 由於這是一個常規的回調函數里面,價值this
不會是你pingApi對象。 您應該保存this
在一般范圍內具有較高的const self = this
或全部回調內部需要是箭頭功能,因此值this
被保留。 try/catch
放在JSON.parse()
周圍,因為如果輸入不是完美的JSON,它可能會拋出。 我需要銷毀/終止插座嗎?
不,請求結束后會自動發生。
一個如何測試呢?
您必須在服務器中創建一個測試路由,該測試路由返回前幾個請求的錯誤情況,然后返回成功的響應,並查看您的代碼是否適用於此。
這是代碼修復的嘗試(未經測試):
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();
}
有關此代碼的其他未解決問題:
this.complete
做什么this
它應該被引用? request.write()
發送POST請求的正文? 我知道您不要求任何外部模塊,但是我這樣做的首選方法是使用http.request()
在http.request()
周圍使用請求-承諾包裝器,因為它為您處理了很多此類代碼(檢查response.status為您服務,為您解析JSON,使用promise接口等)。 您可以看到代碼有多干凈:
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);
})
您對核心節點服務器使用async / await引起了我的興趣,我已嘗試盡可能多地使用這種新的異步功能。
這就是我最終得到的結果: https : //runkit.com/marzelin/pified-ping
const pify = require("util").promisify; const http = require("http"); const hostname = "jsonplaceholder.typicode.com"; const failEndpoint = "/todos/2"; const goodEndpoint = "/todos/4"; let options = { method: "get", path: `${failEndpoint}`, hostname }; async function ping(tries = 0) { return new Promise((res) => { const req = http.request(options, async (response) => { let body = new Buffer(0); response.on("data", (chunk) => { body = Buffer.concat([body, chunk]); }) const on = pify(response.on.bind(response)); await on("end"); let decoded = new Buffer(body, 'base64').toString('utf8') let json = JSON.parse(decoded); if (json.completed) { return res("all good"); } if (tries < 3) { console.log(`retrying ${tries + 1} time`); return res(ping(tries + 1)); } return res("failed"); }) req.on('error', (e) => { console.error(`problem with request: ${e.message}`); }); // write data to request body req.end(); }) } const status = await ping(); "status: " + status
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.