Gulp.series with same source file not working (Async tasks were not awaited)

150 views Asked by At

I have a few gulp tasks which use plop.js to modify a certain file. If I run the tasks by themselves they work just fine.

Now I have a wrapper tasks, where I prompt the user which of the tasks he wants to execute and then I would like to use gulp.series().

They all work, but for those tasks which take the same source file to be modified, it will only apply the first modification. It seems as if the tasks are not really executed sequentally, allowing the first change to be finished and then pass on to the second...

Here is some code:

const gulp = require('gulp')

const strings = {
  polyfill: `polyfill-string-which-is-added-to-file`, // I simplified this one
  modernizr: `{ src: '/js/modernizr-custom.js', async: true, defer: true }`
}

/*
 * Replace specific comments with a string
 * Using plop modify actions
 */
function replaceComment(path, template, pattern) {
  console.log(` Replacing ${pattern} in ${path}...`)

  const nodePlop = require('node-plop')
  const plop = nodePlop()

  const generator = plop.setGenerator('replace', {
    prompts: [],
    actions: [
      {
        type: 'modify',
        path,
        pattern,
        template
      }
    ]
  })

  generator
    .runActions()
    .then(results => {
      console.log(`✅ Sucessfully modified ${path} with ${template}`)
    })
    .catch(err => {
      console.log('err', err)
    })
}

gulp.task('add-polyfill', function(done) {
  console.log('Adding IE11 polyfill to nuxt.config.js ...')

  const path = './nuxt.config.js'
  const pattern = '\/\*\ setup-autocomment-polyfill\ \*\/' // eslint-disable-line
  const template = strings.polyfill

  replaceComment(path, template, pattern)
  done()
})

gulp.task('add-modernizr', function(done) {
  console.log('Adding modernizr script to nuxt.config.js ...')

  const path = './nuxt.config.js'
  const pattern = '\/\*\ setup-autocomment-modernizr\ \*\/' // eslint-disable-line
  const template = strings.modernizr

  replaceComment(path, template, pattern)
  done()
})

gulp.task('setup', function(done) {
   return gulp.series('add-modernizr' , 'add-polyfill')(done)
})

I would be really glad if somebody could give me a pointer here. Do I have to work more with promises? Or why is gulp.series not really doing the thing in a series – I mean the tasks on their own work...

Cheers and Thanks in advance

1

There are 1 answers

0
Merc On

Ok, I found out what the problem was. Indeed it was a thing with promises. The function replaceComment() was started but the done() was called before replaceComment() was finished. So I had to await replaceComment() where I return a promise which only resolves when the modification was finished:

function replaceComment(path, template, pattern) {
  return new Promise((resolve, reject) => {

    console.log(` Replacing ${pattern} in ${path}...`)

    const nodePlop = require('node-plop')
    const plop = nodePlop()

    const generator = plop.setGenerator('replace', {
      prompts: [],
      actions: [
        {
          type: 'modify',
          path,
          pattern,
          template
        }
      ]
    })

    generator
      .runActions()
      .then(results => {
        console.log(`✅ Sucessfully modified ${path} with ${template}`)
        resolve()
      })
      .catch(err => {
        console.log('err', err)
        reject(err)
      })
  })
}


And then for each task I add async await:

gulp.task('add-polyfill', async function(done) {
  console.log('Adding IE11 polyfill to nuxt.config.js ...')

  const path = './nuxt.config.js'
  const pattern = '\/\*\ setup-autocomment-polyfill\ \*\/' // eslint-disable-line
  const template = strings.polyfill

  await replaceComment(path, template, pattern)
  done()
})

Cheers