Skip to content

Instantly share code, notes, and snippets.

@Gaubee
Last active October 7, 2017 16:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Gaubee/1fee1765fa20d90e6aa16ad827bcf082 to your computer and use it in GitHub Desktop.
Save Gaubee/1fee1765fa20d90e6aa16ad827bcf082 to your computer and use it in GitHub Desktop.
基于Generator的流程控制实践
# build
tsc --target es2017 --module CommonJS --lib es2017 "Flow of Find PWD.ts"
# build & debug
tsc --target es2017 --module CommonJS --lib es2017 "Flow of Find PWD.ts" & node --debug-brk --inspect "Flow o f Find PWD.js"
# build & run
tsc --target es2017 --module CommonJS --lib es2017 "Flow of Find PWD.ts" & node "Flow o f Find PWD.js"

执行输出结果:

------STEP 1-------
请输入邮箱
您输入邮箱为 testemailaddress1
邮箱地址格式错误
------STEP 1-------
请输入邮箱
您输入邮箱为 testemail@address2.com
------STEP 2-------
模拟发送邮件到:testemail@address2.com:验证码为:“1111”
验证码已发送 1111
------STEP 3-------
请输入验证码
您输入验证码为 0000
验证码错误
------STEP 3-------
请输入验证码
您输入验证码为 Require send code again
申请重新发送验证码
------STEP 2-------
模拟发送邮件到:testemail@address2.com:验证码为:“1111”
验证码已发送 1111
------STEP 3-------
请输入验证码
您输入验证码为 1111
验证码输入正确
邮箱的密码为: 666666
测试结束并通过
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* 流程的状态机
*/
var FLOW_PROCESS_STATUS;
(function (FLOW_PROCESS_STATUS) {
FLOW_PROCESS_STATUS[FLOW_PROCESS_STATUS["BEFORE_START"] = 0] = "BEFORE_START";
FLOW_PROCESS_STATUS[FLOW_PROCESS_STATUS["INPUT_EMAIL"] = 1] = "INPUT_EMAIL";
FLOW_PROCESS_STATUS[FLOW_PROCESS_STATUS["INPUT_CODE"] = 2] = "INPUT_CODE";
})(FLOW_PROCESS_STATUS || (FLOW_PROCESS_STATUS = {}));
exports.REQUIRE_GET_CODE = "Require send code again"; // 请求重新发送验证码
/**
* 流程的实现
*/
function* Process_Of_Find_Password(options, output) {
var email_url;
// 步骤一:获取邮箱
while (true) {
console.log("------STEP 1-------");
console.log("请输入邮箱");
email_url = yield FLOW_PROCESS_STATUS.INPUT_EMAIL; // 返回状态机
console.log("您输入邮箱为", email_url);
if (!isEmailAddress(email_url)) {
yield new Error("邮箱地址格式错误"); // 抛出错误
}
else {
// 邮箱获取完成,跳出这个步骤(不可再进入),进入下一个步骤
break;
}
}
// 步骤二:发送验证码
while (true) {
console.log("------STEP 2-------");
const code = generatorCheckCode();
sendCodeTOEmail(email_url, code);
console.log("验证码已发送", code);
// 发送完成,进入下一个步骤,这里不跳出(break),因为步骤三执行的途中可能回到步骤二再次回到步骤二,执行重新发送验证码,所以这两个步骤采用包含的行为。
let _step_2_pass = false; // 用于控制步骤二的流程;
// 步骤三:获取验证码
while (true) {
console.log("------STEP 3-------");
console.log("请输入验证码");
const input_code = yield FLOW_PROCESS_STATUS.INPUT_CODE;
console.log("您输入验证码为", input_code);
if (input_code === exports.REQUIRE_GET_CODE) {
console.log("申请重新发送验证码");
break; // 结束步骤三
}
if (input_code === code) {
console.log("验证码输入正确");
_step_2_pass = true; // 结束步骤二
break; // 结束步骤三
}
else {
yield new Error("验证码错误");
}
}
if (_step_2_pass) {
break; // 结束步骤二
}
}
// 最后一个步骤,返回邮箱对应的密码
const pwd = getEmailPassword(email_url);
console.log("邮箱的密码为:", pwd);
output.pwd = pwd;
}
/// 伪代码的简单实现
function isEmailAddress(email_url) {
return email_url.indexOf("@") > -1;
}
function generatorCheckCode() {
return "1111"; //Math.random().toString().substr(2, 6);
}
function sendCodeTOEmail(email_url, code) {
console.log(`模拟发送邮件到:${email_url}:验证码为:“${code}”`);
}
function getEmailPassword(email_url) {
return "666666";
}
// 流程管理
class Flow {
constructor() {
this.output = {};
this.process = Process_Of_Find_Password({
any_config_key: "any config value"
}, this.output);
this._throwed_error = false;
this.status = { value: FLOW_PROCESS_STATUS.BEFORE_START, done: false };
}
nextProcess(arg) {
this.afterError();
const res = this.process.next(arg);
if (res.value instanceof Error) {
this._throwed_error = true;
throw res.value;
}
else {
this.setStatus(res);
}
return res;
}
afterError() {
if (this._throwed_error) {
// 如果抛出过错误,那么执行到下一个暂停点
const next_status_res = this.process.next();
this.setStatus(next_status_res);
this._throwed_error = false;
}
}
emitPropChanged(prop_name) { }
emit(event_name, ...args) { }
setStatus(status) {
if (this.status.value !== status.value) {
this.status = status;
this.emitPropChanged("status");
if (status.done) {
this.emit("end", status.value);
}
}
}
}
/// 测试
/// 测试数据
const input_emails = ["testemailaddress1", "testemail@address2.com"];
const input_codes = ["0000", exports.REQUIRE_GET_CODE, "1111"];
/// 测试逻辑
const flow = new Flow();
while (true) {
if (!flow.status.done) {
try {
switch (flow.status.value) {
case FLOW_PROCESS_STATUS.BEFORE_START:
flow.nextProcess();
break;
case FLOW_PROCESS_STATUS.INPUT_EMAIL:
flow.nextProcess(input_emails.shift());
break;
case FLOW_PROCESS_STATUS.INPUT_CODE:
flow.nextProcess(input_codes.shift());
break;
}
}
catch (err) {
console.error(err.message);
flow.afterError();
}
}
else {
if (flow.output["pwd"] === getEmailPassword()) {
console.log("测试结束并通过");
}
else {
console.log("测试结束但失败");
}
break;
}
}
declare const console: any;
/**
* 流程的状态机
*/
enum FLOW_PROCESS_STATUS {
BEFORE_START,// 初始状态
INPUT_EMAIL,// 请求输入邮箱
INPUT_CODE,// 请求输入验证码
}
export const REQUIRE_GET_CODE = "Require send code again";// 请求重新发送验证码
/**
* 流程的实现
*/
function* Process_Of_Find_Password(options: any, output: any) {
var email_url: string;
// 步骤一:获取邮箱
while (true) {
console.log("------STEP 1-------")
console.log("请输入邮箱");
email_url = yield FLOW_PROCESS_STATUS.INPUT_EMAIL;// 返回状态机
console.log("您输入邮箱为", email_url);
if (!isEmailAddress(email_url)) {
yield new Error("邮箱地址格式错误");// 抛出错误
} else {
// 邮箱获取完成,跳出这个步骤(不可再进入),进入下一个步骤
break;
}
}
// 步骤二:发送验证码
while (true) {
console.log("------STEP 2-------")
const code = generatorCheckCode();
sendCodeTOEmail(email_url, code);
console.log("验证码已发送", code);
// 发送完成,进入下一个步骤,这里不跳出(break),因为步骤三执行的途中可能回到步骤二再次回到步骤二,执行重新发送验证码,所以这两个步骤采用包含的行为。
let _step_2_pass = false;// 用于控制步骤二的流程;
// 步骤三:获取验证码
while (true) {
console.log("------STEP 3-------")
console.log("请输入验证码");
const input_code = yield FLOW_PROCESS_STATUS.INPUT_CODE;
console.log("您输入验证码为", input_code);
if (input_code === REQUIRE_GET_CODE) {
console.log("申请重新发送验证码")
break;// 结束步骤三
}
if (input_code === code) {
console.log("验证码输入正确");
_step_2_pass = true;// 结束步骤二
break;// 结束步骤三
}else{
yield new Error("验证码错误");
}
}
if (_step_2_pass) {
break;// 结束步骤二
}
}
// 最后一个步骤,返回邮箱对应的密码
const pwd = getEmailPassword(email_url);
console.log("邮箱的密码为:", pwd);
output.pwd = pwd;
}
/// 伪代码的简单实现
function isEmailAddress(email_url: string) {
return email_url.indexOf("@") > -1;
}
function generatorCheckCode() {
return "1111";//Math.random().toString().substr(2, 6);
}
function sendCodeTOEmail(email_url: string, code: string) {
console.log(`模拟发送邮件到:${email_url}:验证码为:“${code}”`);
}
function getEmailPassword(email_url?: string) {
return "666666";
}
// 流程管理
class Flow {
output = {}
process: IterableIterator<FLOW_PROCESS_STATUS | Error> = Process_Of_Find_Password({
any_config_key: "any config value"
}, this.output);
private _throwed_error = false;
nextProcess(arg?: any) {
this.afterError();
const res = this.process.next(arg);
if (res.value instanceof Error) {
this._throwed_error = true;
throw res.value;
} else {
this.setStatus(<IteratorResult<FLOW_PROCESS_STATUS>>res);
}
return res;
}
afterError(){
if (this._throwed_error) {
// 如果抛出过错误,那么执行到下一个暂停点
const next_status_res = <IteratorResult<FLOW_PROCESS_STATUS>>this.process.next()
this.setStatus(next_status_res);
this._throwed_error = false;
}
}
status: IteratorResult<FLOW_PROCESS_STATUS> = { value: FLOW_PROCESS_STATUS.BEFORE_START, done: false }
emitPropChanged(prop_name: string) { }
emit(event_name: string, ...args: any[]) { }
setStatus(status: IteratorResult<FLOW_PROCESS_STATUS>) {
if (this.status.value !== status.value) {
this.status = status;
this.emitPropChanged("status");
if (status.done) {
this.emit("end", status.value);
}
}
}
}
/// 测试
/// 测试数据
const input_emails = ["testemailaddress1", "testemail@address2.com"];
const input_codes = ["0000", REQUIRE_GET_CODE, "1111"];
/// 测试逻辑
const flow = new Flow();
while (true) {
if (!flow.status.done) {
try {
switch (flow.status.value) {
case FLOW_PROCESS_STATUS.BEFORE_START:
flow.nextProcess();
break;
case FLOW_PROCESS_STATUS.INPUT_EMAIL:
flow.nextProcess(input_emails.shift());
break;
case FLOW_PROCESS_STATUS.INPUT_CODE:
flow.nextProcess(input_codes.shift());
break;
}
} catch (err) {
console.error(err.message);
flow.afterError();
}
}
else {
if (flow.output["pwd"] === getEmailPassword()) {
console.log("测试结束并通过");
} else {
console.log("测试结束但失败");
}
break;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment