2017-04-13 49 views
0

我这有一口任务之前完成:等功能对于触发下一个节点中的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; 
}); 

除了FTP位伟大的工程。我需要config_module.config()才能完成ftp_module.upload()才能触发。我试着用回调来设置承诺和匿名函数,但这些解决方案都没有工作; FTP功能在配置之前保持开启状态。

如何使ftp_module.upload()函数在发射前等待config_module.config()完成?


编辑:这是我试过的承诺,这仍然不能正常工作:

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

编辑:我希望不要有张贴modules_config.config()代码,因为它是相当长,但我觉得有必要对移动:

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(); 
        }); 
       }); 
      }); 
     }); 
    } 
}; 

正如你所看到的,它返回一个承诺,但FO无论出于何种原因,我仍然无法在FTP任务之后触发它。

+0

你已经说过 - 承诺是正确的实现 –

+0

@JohnVandivier更新了我试过的承诺。它仍然和以前一样,我做错了什么? – JacobTheDev

+0

如果config_module.config()是同步的,但是如果它是异步的,你写的承诺是好的bc resolve()会在它完成之前发生 –

回答

3

您已经对您的问题有一个可能的答案:promises。

问题是你做错了。

在你编辑过程中发布的代码(带有承诺)中,你打电话给你的config_module方法(它似乎是异步的),然后你立即解决承诺。在这种情况下,由于该方法是异步的,因此在对方法进行处理之前,承诺会得到解决,从而导致不需要的行为。

正确的做法是,您应该promisify config_module方法调用自己。这样,在方法执行完成后,您只能“解决”承诺。

由于您没有发布其代码,因此很难说如何配置config_module方法。但是你应该在那里创造一个承诺,然后只有在计算完成时才解决它。所以你可以这样类似:

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

编辑:

后您发布您的config_module代码,这是比较容易看到,唯一缺少的是使用由配置返回的承诺方法来运行ftp_module.upload。然后

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() 
 
}

一种方式做到这一点,

另一种方式来做到这将是你的函数必须链接的回报承诺自己,这样你可以使用这样的函数一个链它们:

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

基本上,当你的链接功能解决它的承诺时,它会调用下一个与你传递的数据来解决。

0

您必须return承诺使其成为同步

但是,您的功能必须返回承诺(如config_module.configftp_module.upload。如果您没有承诺退货功能,则可以使用promisifycallback函数转换为promise

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

你假定他的配置函数已经返回一个promise? –

+0

@MaloGuertin是的,刚刚意识到这一点。编辑.. – Shaharyar

+0

按原来的文章返回承诺,现在不试图运行'upload()'。我用配置函数返回一个承诺(至少我认为我是),但也许我做错了什么?我已经用整个配置功能更新了原文。 – JacobTheDev

0

我建议你使用Async内。这是一个功能强大的模块,有助于构建您的应用程序并使控制流程更加轻松。

异步提供的功能之一是series它允许您逐一调用函数(即第二个函数将不会运行,直到第一个函数完成)。

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'] 
    } 
);