如何在异步功能中运行替换功能?

时间:2019-10-08 10:25:48

标签: javascript async-await

我有一个MongoDB,我想更改一堆模板的值。

我想我得到了变量并替换了旧值。

  findTemplates.forEach(async templateName => {
     const template = await getTemplate( templateName )
     const templateBody = await replaceBody( template.body )
     templateBody.replace('string', 'another-string');
  })

  async function getTemplate (siteName) {
    const id = await emailTemplate.model.findOne({
      'name.de': siteName,
      language: 'en',
      businessUnit: '24ede462ad78fd0d4fd39dfa',
    }).distinct('_id')

    const body = await emailTemplate.model.findOne({
      '_id': id,
    }).distinct('body')

    return {
      id: id,
      body: body
    }
  }

  function replaceBody( body ) {
     return body.replace('one', 'two')
  }

不幸的是,我收到以下错误:

  

UnhandledPromiseRejectionWarning:TypeError:body.replace不是函数templateBody如何在forEach异步函数中使用替换函数?

1 个答案:

答案 0 :(得分:1)

我重写了您的示例,因此我可以对其进行仿真,该示例可以按您的预期工作,但不会引发异常。因此,我检测到的唯一错误是在此行中:

 // You must not put await here because replace body does not return a Promise.
 const templateBody = replaceBody( template.body )

const allTemplates = []

for (let i = 0; i <= 10; i++) {
  allTemplates.push({
   _id: faker.random.uuid(),
   'name.de': faker.internet.domainName(),
   language: faker.random.locale(),
   businessUnit: faker.random.uuid(),
   body: faker.lorem.paragraph()
  })
}

const findTemplates = allTemplates.map(item => item['name.de'])

const emailTemplate = {
   model: {
      findOne: params => {
         const found = allTemplates.find(item => params._id ? item._id === params._id : item['name.de'] === params['name.de'])
         const result = Object.assign({}, found, params)

         result.distinct = function (key) {
          return Promise.resolve(this[key])
         }
         
         return result
      }
   }
}

async function getTemplate (siteName) {
  const id = await emailTemplate.model.findOne({
    'name.de': siteName,
     language: 'en',
     businessUnit: '24ede462ad78fd0d4fd39dfa',
  }).distinct('_id')

  const body = await emailTemplate.model.findOne({
    '_id': id,
  }).distinct('body')

  return {
    id: id,
    body: body
  }
}

function replaceBody( body ) {
   return body.replace('one', 'two')
}

findTemplates.forEach(async templateName => {
   try {
     const template = await getTemplate( templateName )
     // You must not put await here because replace body does not return a Promise.
     const templateBody = replaceBody( template.body )
     console.log(templateBody.replace('string', 'another-string'))
   } catch (err) {
     console.err(`Error procesing template: ${templateName}: ${err}`)
   }
})

/**
 * Alternatively you can do:

Promise.all(findTemplates.map(async templateName => {
   const template = await getTemplate( templateName )
   // You must not put await here because replace body does not return a Promise.
   const templateBody = replaceBody( template.body )
   console.log(templateBody.replace('string', 'another-string'))
}).catch(err => console.err)
*/
 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/Faker/3.1.0/faker.min.js"></script>

因此请注意您的问题:如何在forEach异步函数中使用replace函数?答案是,您可以像执行操作一样使用replace(但请修复此行,并检查@ t-j-crowder的评论内容)。

如果主体不是字符串,则应检查它是哪种对象,是否具有替换功能(是否具有),以及该替换功能是否返回(无)Promise。