在字符串替换中使用Promise

时间:2018-09-20 05:10:08

标签: javascript

我对诺言比较陌生,而且遇到了问题。

我有一个函数,希望能够对给定的文本进行一堆字符串替换,其中一些包含从api调用返回的值。

parseText(text) {
  text.replace(/\n|\r\n|\r/g, ' ')
  .replace(/&/g, '&')
  .replace(/&lt;/g, '<')
  .replace(/&gt;/g, '>')
  .replace(/<#(C\w+)\|?(\w+)?>/g, (match, id, read) => {
    return apiMethod(id).then(resp => resp.name)
  })
  .then(newText => {
    return newText.replace(/(-\w+)>/g, (match, id) => {
      apiMethod(id).then(resp => resp.name)
    }
  });
}

如何使替换与apiMethod Promise的返回值一起使用?

1 个答案:

答案 0 :(得分:2)

一个选择是为每个请求创建一个Promises数组,在数组上调用Promise.all,然后创建一个由id索引的对象(正则表达式中的第一组)。然后,再次调用.replace,并用适当的索引键替换。因为您必须异步替换多次,所以将其放入自己的函数中以使代码变干:

const asyncReplace = async (str, regex) => {
  const promises = [];

  // does not actually replace anything, just builds the promises:
  str.replace(regex, (match, id, read) => {
    promises.push(apiMethod(id).then(resp => [id, resp.name]));
  });
  const results = await Promise.all(promises);
  const replacements = results.reduce((a, [id, name]) => {
    a[id] = name;
    return a;
  }, {});
  return str.replace(regex, (match, id, read) => replacements[id]);
}

parseText(text) {
  const str = text.replace(/\n|\r\n|\r/g, ' ')
  .replace(/&amp;/g, '&')
  .replace(/&lt;/g, '<')
  .replace(/&gt;/g, '>');
  return asyncReplace(str, /<#(C\w+)\|?(\w+)?>/g)
    .then((str2) => asyncReplace(str2, /<#(C\w+)\|?(\w+)?>/g))
}

实时摘要:

// encloses the match in underscores
const apiMethod = substr => Promise.resolve('_' + substr + '_');

const asyncReplace = async (str, regex) => {
  const promises = [];

  // does not actually replace anything, just builds the promises:
  str.replace(regex, (match, id, read) => {
    promises.push(apiMethod(id).then(resp => [id, resp]));
  });
  const results = await Promise.all(promises);
  const replacements = results.reduce((a, [id, name]) => {
    a[id] = name;
    return a;
  }, {});
  return str.replace(regex, (match, id, read) => replacements[id]);
}

function parseText(text) {
  // put underscores around every space...
  return asyncReplace(text, /( )/g)
  // ...twice:
    .then((str2) => asyncReplace(str2, /( )/g))
}
parseText('foo bar baz')
  .then(res => console.log(res));