我目前正在努力在AWS Lambda上编写函数。我想将RSS feed转换为JSON,并在制作Lambda端点时将其作为正文中的响应。
我正在使用npm package将RSS转换为JSON。但是,当我运行代码时。我看到在RSS URL的转换中未定义。这是下面的代码:
const feed = require('rss-to-json');
exports.handler = async (event) => {
let rssFeed = event.queryStringParameters.rssFeed;
let rssAsJsonData = convertRssIntoJson(rssFeed);
return sendRes(200, rssAsJsonData);
};
const sendRes = (status, body) => {
var response = {
isBase64Encoded: true|false,
statusCode: status,
headers: {
"Content-Type": "application/json"
},
body: body,
};
return response;
};
function convertRssIntoJson (rssFeed) {
console.log(rssFeed);
return feed.load(rssFeed, function(err, rss){
if(err) {
console.log("Error: ${err}");
return;
}
console.log(rss)
return rss;
});
};
但是,当undefined
时,我在日志中得到console.log(rssAsJsonData)
。
但是,在调试时,我将正文更改为console.log(rss)
时可以看到body: json.stringify("TESTING")
正常工作
但是,它仅在登录到控制台时有效,而在我尝试将其传递到正文body: body,
时却无效,我似乎找不到错误所在。我正在为该项目从Ruby迁移到JavaScript,也许我错过了一些东西。
答案 0 :(得分:2)
function convertRssIntoJson (rssFeed) {
console.log(rssFeed);
return feed.load(rssFeed, function(err, rss){
if(err) {
console.log("Error: ${err}");
return;
}
console.log(rss)
return rss;
});
};
上面的代码是一个回调。在内部,feed.load是异步的,这使您的回调可以异步执行。
现在,当您像这样调用函数时
let rssAsJsonData = convertRssIntoJson(rssFeed);
您在rss
中的convertRssIntoJson
对象尚未保存任何值,因为到目前为止尚未填充回调。这就是您的undefined
的来源。
默认情况下,回调本身不会使代码异步,但是NodeJS可与非阻塞IO模型一起使用,并且由于feed.load是IO调用,因此它将异步执行。
您现在有几个选择,但是我只列出两个。不太好,一个不错的解决方案:
1)解决该问题的一种不错的方法是将回调作为参数添加到convertRssIntoJson
函数中,并将该rss
对象的值传递给上游。不太好的完整代码可以在下面找到:
const feed = require('rss-to-json');
exports.handler = async (event) => {
let rssFeed = event.queryStringParameters.rssFeed;
convertRssIntoJson(rssFeed, (err, data) => {
if (err) {
return sendRes(500, { message: 'There was an err: ' + err.message })
}
return sendRes(200, data)
})
};
const sendRes = (status, body) => {
var response = {
isBase64Encoded: true | false,
statusCode: status,
headers: {
"Content-Type": "application/json"
},
body: body,
};
return response;
};
const convertRssIntoJson = (rssFeed, callback) => {
console.log(rssFeed);
feed.load(rssFeed, function (err, rss) {
if (err) {
console.log("Error: ${err}");
callback(err, undefined)
}
console.log(rss)
callback(undefined, rss)
});
};
2)这是一个不错,干净,优雅且推荐的解决方案。像这样将您的回调包装在Promise中
function convertRssIntoJson(rssFeed) {
console.log(rssFeed);
return new Promise((res, rej) => {
feed.load(rssFeed, function (err, rss) {
if (err) {
console.log("Error: ${err}");
return rej(err)
}
console.log(rss)
return res(rss)
});
})
};
由于您的处理程序是async
,这意味着它只能await
兑现承诺。
因此,您的客户代码现在非常简单:
return sendRes(200, await convertRssIntoJson(rssFeed));
您的最终代码将如下所示(为了使用箭头功能,我进行了一些重构):
const feed = require('rss-to-json');
exports.handler = async (event) => {
let rssFeed = event.queryStringParameters.rssFeed;
return sendRes(200, await convertRssIntoJson(rssFeed));
};
const sendRes = (status, body) => {
var response = {
isBase64Encoded: true | false,
statusCode: status,
headers: {
"Content-Type": "application/json"
},
body: body,
};
return response;
};
const convertRssIntoJson = (rssFeed) => {
console.log(rssFeed);
return new Promise((res, rej) => {
feed.load(rssFeed, (err, rss) => {
if (err) {
console.log("Error: ${err}");
return rej(err)
}
console.log(rss)
return res(rss)
});
})
};
如果您想了解有关异步/等待的更多信息,可以在here中查看。
EDIT :针对解决方案1)的代码重构和代码添加