0

I am making a Yeoman generator to install CraftCMS with some custom settings and files preloaded for faster development.

I've got the to point where the script does a composer create-project craftcms/craft. For me, the next logical step would be to cd into the folder and run the craft installer craft install.

I just can't figure out how to let the lines of code run synchronous. At the moment it is running everything at the same time, which of course will run into errors.

This is my code:

'use strict';
const generator = require('yeoman-generator');
const chalk = require('chalk');
const yosay = require('yosay');
let init;
module.exports = class extends generator {
    async initializing() {
        this.log(yosay(chalk.blue('Hey!') + '\n' + 'Welcome to the Visited Installer!' + '\n\n' + 'Let\'s start a project together!'));
        init = await this.prompt([{
            type: 'input',
            name: 'name',
            message: 'What is the name of your new project?',
        }]);
        this.log(yosay(chalk.blue(init.name) + ', Great!' + '\n\n' + 'Let\'s start by downloading the latest version of CraftCMS.'));
    }
    install() {
        this.spawnCommand('composer', ['create-project', 'craftcms/craft', init.name]);
        this.log(yosay(chalk.blue('Done!') + '\n\n' + 'The next step is installing CraftCMS, Don\'t worry, I\'ve got this!'));
        this.spawnCommand('cd', [init.name]);
        this.spawnCommand('craft', ['install']);
    }
};

I have tried reading about asynchronous and synchronous programming in JS, but due to the fact that I am not a native english speaker, and the fact that I don't do a lot with JS (I mostly use PHP) make it hard for me to understand the logic behind it.

Update: I changed my post, I mixed up async and sync in my head. Problem remains that everything within my install() function runs at the same time: this.log does not wait for this.spawnCommand to be done downloading and setting up the files..

  • async/await is syntax "sugar" for Promises. does `this.prompt` return a promise? there are no `await` in `install()` so, why is it `async`? – Bravo Oct 24 '18 at 11:34
  • `I just can't figure out how to let the lines of code run asynchronous. At the moment it is running everything at the same time, which of course will run into errors` - if everything is running at the same time, it **is** asynchronous. perhaps you need to add `await` in front of all those `this.spawnCommand`s - which would explain why `install` is `async install()` – Bravo Oct 24 '18 at 11:36
  • Hey, sorry for my misunderstanding, I mixed up async and sync. I edited my post so it'll make more sence @Bravo – Mike Snoeren Oct 24 '18 at 11:53
  • have you tried putting `await`s where I suggested – Bravo Oct 24 '18 at 11:58
  • Yes, no success. I think I know what is going wrong; The lines of code are run synchronous, but it starts the second line after firing `this.spawnCommand` and not wait for this to be done. Can this be true? – Mike Snoeren Oct 24 '18 at 12:02

1 Answers1

0

The problem is that spawnCommand is inherently asynchronous and it doesn't provide you with any means of waiting until the command finishes. It does not take a callback argument, nor does it return a promise.

However there is another command: spawnCommandSync, which promises to do its work synchronously. Give it a try.

Rene Saarsoo
  • 13,580
  • 8
  • 57
  • 85
  • Thank you, that is exactly what I need! Due to the fact that I mixed async and sync in my head I totally didn't think about that anymore! Thanks :) – Mike Snoeren Oct 24 '18 at 12:08