我一直在研究以下代码。我是Promises和异步代码的新手,但我在这里和其他地方读过一些非常方便的帖子,在下面创建代码的过程中描述它们。
目的是创建一个函数来检测作者插入链接标记的文章中的文本,并正确地将它们替换为具有相同名称的另一篇文章的链接(如果存在)。在这种情况下,指向另一篇名为articleName
的文章的文本标记链接将写为<<articleName>>
- 我知道样式<<texthere>>
可能会导致一些问题,但实际的标记本身可能会发生变化。我只是想让文本替换正确返回,所以我可以将新字符串传递给要呈现的响应。
我对这个问题感到茫然,在这里 - 似乎在linkedArticle
传递之后的某个时刻,承诺链被打破了。我认为使用正则表达式匹配(我也使用了string.js的between
函数,结果相同)不能与Promise.resolve()
一起使用。我输出的内容只有matchedArray
到undefined
的字符串。我可能会过度使用return
和Promise.resolve()
,我不确定。
我正在使用Node.js和Mongoose。我玩过使用本机承诺,async
,string.js
和underscore
。下面的代码使用async和string.js。
我已经尽可能多地整理了下面的代码。为长期争论传递+吨回报和结算的道歉(这可能是我问题的原因?)。这是我正在做的事情之一,以检查连锁可能破坏的地方;我为这篇文章保留它只是为了分隔一些东西,希望提高可读性。
文章架构很简单,引入了一个字符串条目,这是我用于测试目的的。
//Show article
var show = (req, res, next) => {
let id = req.params.id;
Article.findOne({_id : id}).populate('_author').then(function(article) {
if (!article) return res.render('404');
return Promise.resolve(replaceTextLinks(article.introduction)).then(function(text){
console.log("Returned text is" + text)
});
});
}
var replaceTextLinks = (text) => {
let regExp = /<<([a-zA-z0-9 ]+)>>/g;
console.log("Initial passed in text is: " + text)
return Promise.resolve(text.match(regExp)).then(function(matchArray){
console.log("Matched array is: " + matchArray);
async.each(matchArray, function(matchText){
console.log("Matched Text is: " + matchText);
return linkArticle(text, matchText);
});
}).catch(function(err){
console.log("Error encountered: %s", err);
});
}
var linkArticle = (text, matchText) => {
let regExp = /([a-zA-Z]+)/g;
return Promise.resolve(matchText.match(regExp)).then(function(linkedArticle){
console.log("Linked Article is: " + linkedArticle);
return Promise.resolve(matchArticle(text, matchText ,linkedArticle));
})
}
var matchArticle = (text, matchText, linkedArticle) => {
return Article.findOne({title:linkedArticle}).then(function(matchedArticle) {
console.log("matchedArticle is: " + matchedArticle);
if(matchedArticle) {
return Promise.resolve(replaceTextWithArticle(text, matchText, matchedArticle, linkedArticle));
}
})
}
var replaceTextWithArticle = (text, matchText, matchedArticle, linkedArticle) => {
console.log("Replacing initial text: " + text);
replacedText = '<a href=' + '/articles/view/' + matchedArticle._id + ">" + linkedArticle + "</a>"
return Promise.resolve(S(text).replaceAll(matchText, replacedText).s).then(function(newText){
console.log("Replaced text is: " + newText);
return Promise.resolve(newText);
})
}
以下是运行'show'时的控制台输出。文章集合中的其他文章名为Privacy
,与传入的标记<<Privacy>>
相匹配。在控制台上的LinkedArticle告诉我打嗝在某处之后,返回的文本未定义,但我可能是错的。即使是带有三个标签的文章也是如此。
Initial passed in text is: This article contains a tag, <<Privacy>>.
Matched array is: <<Privacy>>
Matched Text is: <<Privacy>>
Linked Article is: Privacy
Returned text is undefined
matchedArticle is: { _id: 5909f3efe8d05c4e3827c4d1,
title: 'Privacy',
_author: 5909f3eee8d05c4e3827c4d0,
category: 'Security',
introduction: 'Type your article\'s introduction here...',
contents: 'Type your article\'s content here...',
conclusion: 'Type your article\'s conclusion here...',
__v: 0,
published: false }
Replacing initial text: This article contains a tag, <<Privacy>>.
Replaced text is: This article contains a tag, <a href=/articles/view/5909f3efe8d05c4e3827c4d1>Privacy</a>.
非常感谢您提供的任何帮助;我很遗憾,承诺链似乎在破坏自己。
答案 0 :(得分:1)
首先,您过度使用Promise.resolve
- 事实上,您不需要在代码中使用
其次,Promise + async.js === nothing but trouble
所以,删除所有无用的Promise.resolve
,并用Promise.all替换async.each,并依赖于matchArticle
是唯一需要返回Promise的函数,它做了,因为.findOne
显然可以,您的代码可以大大简化 - 下面的代码并没有使用我可以添加到您的代码中的所有ES6调整,但我不想要代码在答案中超越你的能力
const show = (req, res, next) => {
const id = req.params.id;
Article.findOne({_id: id}).populate('_author').then((article) => {
if (!article) {
return res.render('404');
}
return replaceTextLinks(article.introduction).then((text) => {
console.log("Returned text is" + text)
});
});
}
const replaceTextLinks = (text) =>
Promise.all(text.match(/<<([a-zA-z0-9 ]+)>>/g).map(matchText => linkArticle(text, matchText)));
const linkArticle = (text, matchText) =>
matchArticle(text, matchText, matchText.match(/([a-zA-Z]+)/g));
const matchArticle = (text, matchText, linkedArticle) => {
return Article.findOne({title:linkedArticle}).then(function(matchedArticle) {
console.log("matchedArticle is: " + matchedArticle);
if(matchedArticle) {
return replaceTextWithArticle(text, matchText, matchedArticle, linkedArticle);
}
});
};
const replaceTextWithArticle = (text, matchText, matchedArticle, linkedArticle) => {
console.log("Replacing initial text: " + text);
replacedText = '<a href=' + '/articles/view/' + matchedArticle._id + ">" + linkedArticle + "</a>"
return S(text).replaceAll(matchText, replacedText).s;
};