2017-04-13 4 views
0

Ich habe diese Aufgabe Schluck bekam:Warten Sie eine Funktion vor dem Brennen die nächste in Knoten zu beenden JS

// default task, runs through all primary tasks 
gulp.task("default", ["media", "scripts", "styles", "html"], function() { 
    // notify that task is complete 
    gulp.src("gulpfile.js") 
     .pipe(plugins.gulpif(ran_tasks.length, plugins.notify({title: "Success!", message: ran_tasks.length + " task" + (ran_tasks.length > 1 ? "s" : "") + " complete! [" + ran_tasks.join(", ") + "]", onLast: true}))); 

    // trigger FTP task if FTP flag is passed 
    if (plugins.argv.ftp) { 
     config_module.config(gulp, plugins, settings); 
     ftp_module.upload(gulp, plugins, settings, ran_tasks, on_error); 
    } 

    // reset ran_tasks array 
    ran_tasks.length = 0; 
}); 

die großen Werke, mit Ausnahme der Bit-FTP. Ich brauche config_module.config() zu beenden, bevor ftp_module.upload() ausgelöst werden kann. Ich habe versucht, Versprechen und anonyme Funktionen mit Rückrufen einzurichten, aber keine dieser Lösungen funktionierte; Die FTP-Funktion feuert vor der Konfiguration.

Wie kann ich die ftp_module.upload() Funktion warten auf config_module.config() zu beenden, bevor feuern?


EDIT: Hier ist das Versprechen, das ich versuchte, die immer noch nicht richtig funktioniert:

new Promise(function (resolve) { 
    config_module.config(gulp, plugins, settings); 
    resolve(); 
}).then(function() { 
    ftp_module.upload(gulp, plugins, settings, ran_tasks, on_error); 
}); 

EDIT: Ich hatte gehofft, nicht zu haben, die modules_config.config() Code zu schreiben, da es ziemlich ist lang, aber ich denke, dass es notwendig ist, sich zu bewegen:

module.exports = { 
    // config task, generate configuration file for FTP & BrowserSync and prompt dev for input 
    config(gulp, plugins, settings) { 
     // generate settings.json and start other functions 
     const generate_config = function (callback) { 
      return plugins.fs.stat("./settings.json", function (err) { 
       if (err !== null) { 
        const json_data = 
        `{ 
         "ftp": { 
          "dev": { 
           "hostname": "", 
           "port":  "21", 
           "mode":  "ftp", 
           "username": "", 
           "password": "", 
           "path":  "" 
          }, 
          "dist": { 
           "hostname": "", 
           "port":  "21", 
           "mode":  "ftp", 
           "username": "", 
           "password": "", 
           "path":  "" 
          } 
         }, 
         "browsersync": { 
          "dev": { 
           "proxy": "", 
           "port": "", 
           "open": "", 
           "notify": "" 
          }, 
          "dist": { 
           "proxy": "", 
           "port": "", 
           "open": "", 
           "notify": "" 
          } 
         } 
        }`; 

        plugins.fs.writeFile("./settings.json", json_data, "utf8", function() { 
         callback(); 
        }); 
       } else if (typeof callback === "function") { 
        callback(); 
       } 
      }); 
     }; 

     // configue JSON data 
     const configure_json = function (namespace, options, env, callback) { 
      const prompts = []; 

      // construct the prompts 
      Object.keys(options).forEach(option => { 
       const properties = options[option]; 

       // construct the prompt 
       const prompt  = { 
        name: option, 
        message: namespace + " " + option + ": ", 
       }; 

       // construct the prompt 
       Object.keys(properties).forEach(property => { 
        prompt[property] = properties[property]; 
       }); 

       // put the prompt in the array 
       prompts.push(prompt); 
      }); 

      // prompt the user 
      return gulp.src("./settings.json") 
       .pipe(plugins.prompt.prompt(prompts, function (res) { 
        // open settings.json 
        const file = plugins.json.read("./settings.json"); 

        // update data in JSON 
        Object.keys(options).forEach(option => { 
         file.set(namespace + "." + env + "." + option, res[option]); 
         settings[namespace][option] = res[option]; 
        }); 

        // write updated file contents 
        file.writeSync(); 

        if (typeof callback === "function") { 
         callback(); 
        } 
       })); 
     }; 

     return new Promise (function (resolve) { 
      // get the target environment 
      const env = plugins.argv.dist ? "dist" : "dev"; 

      // generate settings.json 
      generate_config(function() { 
       // read browsersync settings from settings.json 
       settings.browsersync.proxy = plugins.json.read("./settings.json").get("browsersync." + env + ".proxy"); 
       settings.browsersync.port = plugins.json.read("./settings.json").get("browsersync." + env + ".port"); 
       settings.browsersync.open = plugins.json.read("./settings.json").get("browsersync." + env + ".open"); 
       settings.browsersync.notify = plugins.json.read("./settings.json").get("browsersync." + env + ".notify"); 

       // read FTP settingss from settings.json 
       settings.ftp.host = plugins.json.read("./settings.json").get("ftp." + env + ".hostname"); 
       settings.ftp.port = plugins.json.read("./settings.json").get("ftp." + env + ".port"); 
       settings.ftp.mode = plugins.json.read("./settings.json").get("ftp." + env + ".mode"); 
       settings.ftp.user = plugins.json.read("./settings.json").get("ftp." + env + ".username"); 
       settings.ftp.pass = plugins.json.read("./settings.json").get("ftp." + env + ".password"); 
       settings.ftp.path = plugins.json.read("./settings.json").get("ftp." + env + ".path"); 

       // configure FTP credentials 
       configure_json("ftp", { 
        hostname: { 
         default: settings.ftp.host, 
         type: "input", 
        }, 
        port: { 
         default: settings.ftp.port, 
         type: "input", 
        }, 
        mode: { 
         default: settings.ftp.mode === "ftp" ? 0 : settings.ftp.mode === "tls" ? 1 : settings.ftp.mode === "sftp" ? 2 : 0, 
         type: "list", 
         choices: ["ftp", "tls", "sftp"], 
        }, 
        username: { 
         default: settings.ftp.user, 
         type: "input", 
        }, 
        password: { 
         default: settings.ftp.pass, 
         type: "password", 
        }, 
        path: { 
         default: settings.ftp.path, 
         type: "input", 
        }, 
       }, env, function() { 
        // configure BrowserSync settings 
        configure_json("browsersync", { 
         proxy: { 
          default: settings.browsersync.proxy === "" ? "localhost" : settings.browsersync.proxy, 
          type: "input", 
         }, 
         port: { 
          default: settings.browsersync.port === "" ? "8080" : settings.browsersync.port, 
          type: "input", 
         }, 
         open: { 
          default: settings.browsersync.open === "" ? "external" : settings.browsersync.open, 
          type: "input", 
         }, 
         notify: { 
          default: settings.browsersync.open === "" ? "false" : settings.browsersync.open, 
          type: "input", 
         }, 
        }, env, function() { 
         // resolve the promise 
         resolve(); 
        }); 
       }); 
      }); 
     }); 
    } 
}; 

Wie Sie sehen können, ist es ein Versprechen zurückkehrt, aber fo Aus irgendeinem Grund kann ich die FTP-Aufgabe immer noch nicht auslösen.

+0

Sie sagten es bereits - Versprechen der Umsetzung –

+0

@JohnVandivier mit dem Versprechen, aktualisiert richtig habe ich versucht. Es tut immer noch das Gleiche wie zuvor, mache ich etwas falsch? – JacobTheDev

+0

Die Art, wie Sie das Versprechen geschrieben haben, ist in Ordnung, wenn config_module.config() synchron ist, aber wenn es asynchron ist, haben Sie ein Problem bc resolve() wird passieren, bevor es fertig ist –

Antwort

3

Sie haben bereits eine mögliche Antwort auf Ihre Frage: Versprechungen.

Das Problem ist, dass Sie es falsch machen.

In dem Code, den Sie in Ihrer Bearbeitung (mit Versprechungen) gepostet haben, rufen Sie Ihre config_module Methode (die asynchron zu sein scheint) und dann lösen Sie das Versprechen direkt danach. Da die Methode in diesem Szenario asynchron ist, wird das Versprechen gelöst, bevor die Verarbeitung der Methode config erfolgt, was zu einem unerwünschten Verhalten führt.

Der richtige Ansatz ist, dass Sie den Methodenaufruf config_module selbst Promistificieren sollten. Auf diese Weise lösen Sie das Versprechen nur, nachdem die Ausführung der Methode vollständig ausgeführt wurde.

Es ist schwer zu sagen, wie die config_module Methode sein sollte, da Sie seinen Code nicht veröffentlicht haben. Aber Sie sollten dort ein Versprechen erstellen und es dann erst lösen, wenn die Berechnung abgeschlossen ist. So konnte man so etwas wie:

config_module.config(gulp, plugins, settings) 
    .then(function() { 
     ftp_module.upload(gulp, plugins, settings, ran_tasks, on_error); 
    }); 

EDIT:

Nachdem Sie Ihren config_module Code geschrieben, war es leichter zu sehen, dass das einzige, was fehlt, das Versprechen von dem Config wieder zu verwenden war Methode, um die ftp_module.upload innerhalb des .then Block laufen

0

new Promise(function (resolve) { 
 
    config_module.config(gulp, plugins, settings,()=>{promise.resolve()}); 
 
}).then(function() { 
 
    ftp_module.upload(gulp, plugins, settings, ran_tasks, on_error); 
 
}); 
 

 
config_module.config = (gulp, plugins, settings, doneCallback){ 
 
    //...do stuff 
 
    doneCallback() 
 
}

Eine Möglichkeit, es zu tun,

eine andere Art und Weise, es zu tun wäre, dass Ihre Funktion, die Rückkehr verspricht sich verkettet werden müssen, auf diese Weise eine Funktion wie diese verwenden können eine Ketten ihnen:

var pipeline = (tasks, arg) => { 
 
    return tasks.reduce((promise, fn) => { 
 
    return promise.then(fn) 
 
    }, Promise.resolve(arg)) 
 
}

Grundsätzlich, wenn Ihre verketteten Funktionen auflösen, ist es vielversprechend, dass es den nächsten mit den Daten aufruft, die Sie zur Lösung übergeben.

0

Sie müssen return das Versprechen, es Sync zu machen.

Aber dafür muss Ihre Funktion ein Versprechen zurückgeben (wie config_module.config und ftp_module.upload). Wenn Sie keine Rückgabefunktion haben, konvertieren Sie Ihre callback Funktion in promise mit promisify.

new Promise(function() { 
    var _config = Promise.promisify(config_module.config); //make your callback a Promise 
    return _config(gulp, plugins, settings); //now call the function, and return its result (which is a Promise now) 
}).then(function() { 
    var _upload = Promise.promisify(ftp_module.upload); 
    return _upload(gulp, plugins, settings, ran_tasks, on_error); 
}); 
+0

Sie gehen davon aus, dass seine Config-Funktion bereits ein Versprechen liefert? –

+0

@MaloGuertin Ja, das ist mir gerade klar geworden. Editing .. – Shaharyar

+0

Das Versprechen, wie ich es im ursprünglichen Beitrag habe, zurückgeben, es ist jetzt nicht versuchen, 'upload()' überhaupt auszuführen. Ich gebe ein Versprechen mit der Config-Funktion (zumindest denke ich, ich bin), aber vielleicht mache ich etwas falsch? Ich habe den ursprünglichen Beitrag mit der gesamten Konfigurationsfunktion aktualisiert. – JacobTheDev

0

ich Sie Async verwenden vorschlagen. Es ist ein leistungsfähiges Modul, das hilft, Ihre Anwendung zu strukturieren und den Kontrollfluss zu vereinfachen.

Eine der Funktionen, die Async bereitstellt, ist series, mit der Sie Funktionen einzeln aufrufen können (d. H. Die zweite Funktion wird erst ausgeführt, wenn die erste Funktion abgeschlossen ist).

async.series(
    [ 
     function(callback) { 
     // ... 
     config_module.config(); 
     // do some more stuff if needed ... 
     callback(null, 'one'); 
     }, 
     function(callback) { 
     // ... 
     ftp_module.upload(); 
     // do some more more stuff if needed ... 
     callback(null, 'two'); 
     } 
    ], 
    // optional callback 
    function(err, results) { 
    // results is now equal to ['one', 'two'] 
    } 
); 
Verwandte Themen