节点承诺链似乎在字符串匹配时被破坏,如何解决?

时间:2017-05-03 16:03:37

标签: javascript node.js mongoose promise

我一直在研究以下代码。我是Promises和异步代码的新手,但我在这里和其他地方读过一些非常方便的帖子,在下面创建代码的过程中描述它们。

目的是创建一个函数来检测作者插入链接标记的文章中的文本,并正确地将它们替换为具有相同名称的另一篇文章的链接(如果存在)。在这种情况下,指向另一篇名为articleName的文章的文本标记链接将写为<<articleName>> - 我知道样式<<texthere>>可能会导致一些问题,但实际的标记本身可能会发生变化。我只是想让文本替换正确返回,所以我可以将新字符串传递给要呈现的响应。

我对这个问题感到茫然,在这里 - 似乎在linkedArticle传递之后的某个时刻,承诺链被打破了。我认为使用正则表达式匹配(我也使用了string.js的between函数,结果相同)不能与Promise.resolve()一起使用。我输出的内容只有matchedArrayundefined的字符串。我可能会过度使用returnPromise.resolve(),我不确定。

我正在使用Node.js和Mongoose。我玩过使用本机承诺,asyncstring.jsunderscore。下面的代码使用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>.

非常感谢您提供的任何帮助;我很遗憾,承诺链似乎在破坏自己。

1 个答案:

答案 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;
};