追求JS小姊姊系列 Day15 -- 方函式的能力展现:认识生成器,工具人更神气(下)

前情提要

生成器模式背後似乎有一个依循的规则

方函式:关於生成器运作的原理,其实跟工具人蛮像的
:又在拖台钱吗


果然是个工具人,就该用工具人视角 来诠释生成器原理吧

故事主要角色:

  1. 生成器:工具人
  2. 迭代器:以为能发展但其实是主仆的关系(老王新歌好听
  3. 呼叫:知道他她喜欢你你的你你
  4. 回传:回覆你她有男友了

故事开始:

(以下内容节录於忍者2对於生成器执行原理的说明)

初始呼叫生成器这项动作,并不是真的执行它,而是建立一个迭代器,并透过迭代器来向生成器请求回传(yield内容)。

翻译: 最初你会跟工具人互动,并不是真的想认识他,而是想建立可联络的关系,就能透过关系向工具人完成需求。

执行完後生成器状态会转为:暂停执行,等待下次的(next方法)再启动,

翻译: 当他处理完你要他做的事情後,你很自然的就不理他了,这时候他会耐心等待你的下个需求


方函式:讲到这里,你是否有个疑问?如果按照工具人故事脉落推敲,所以生成器没有终止的时候对吗?

一般情境下答案是错的

方函式:还记得第四个角色回传吗?当她决定回覆你的心意,告诉你她有男友时,就会终止了。
当然现实生活是不是这样我不确定


认真的生成器执行原理:

现在,我们再重看一次,生成器的各个状态:

  1. 待命中:当产生新的生成器就是这个状态,此时并不会执行生成器的程序码。

  2. 执行中:在此状态下,会根据生成器内最初的/生成器最後暂停的位置继续执行,==当对应的迭代器next呼叫时==,发现尚需执行的程序码时,就会执行到下一个yield表达式。

  3. 暂停生产:当遇到yield表达式时,生成器会回传一个物件,接着转为暂停执行状态,直到下次的next方法呼叫。

  4. 完成:当生成器处於执行中,执行到return,或是发现生成器所有yield内容都被执行时,就会进入完成状态。

图片引用来源:Secrets of the JavaScript Ninja, 2nd Edition.pdf

所以现实生活怎麽使用生成器 工具

  1. 规划半天时程
    就算好几个行程时间不确定,也一样没问题(下图没有加入时间因素)

没有生成器的情境

function buyBreakfast(){
    console.log("早餐买好了"); 
    return function doTheLaundry(){
        console.log("衣服洗好了");
        return function walkTheDog(){
            console.log("遛好狗了");
            return function buyLunch(){
                console.log("午餐买好了")
            };
        };
    };
};

有生成器的情境
就算你时间上有不确定的因素(setTimeout),行程也能按照你预期的顺序来执行。

//创造随机时间的函式
function getRandomTime(x){
    return Math.floor(Math.random()*x)+1;
};
//参考:https://ithelp.ithome.com.tw/articles/10197904

function* planHalfOfDay(i){
    
    yield setTimeout(function buyBreakfast(){console.log("买好早餐"); },getRandomTime(5));
    yield setTimeout(function doTheLaundry(){console.log("洗好衣服!"); },getRandomTime(5));
    yield setTimeout(function walkTheDog(){console.log("遛狗好了!"); },getRandomTime(5));
    yield setTimeout(function buyLunch(){console.log("买好午餐"); },getRandomTime(5));
}

const control = planHalfOfDay();
control.next();

  1. 好工具就是要一直用 --- 如何让生成器不终止

    方函式:舍不得工具人离开(终止)吗?while建立一个永不停止的生成器,让你一时用一时爽,一直用一直爽。

    :JS到底是怎样的人啊..

function* keepToolManAliveForever(i){
    
    //充满热忱的初期
    yield "帮我做OX";
    yield "帮QQ";
    while(true){
        const keepHisAlive = yield "你是我特别的(工具)人";
        console.log(keepHisAlive);
        const doSomething = yield;
        console.log(doSomething);
    }
} 

let controlWay = keepToolManAliveForever();
controlWay.next();
  1. 任务分流 -- 重要的要先做
    方函式:工具人要做的事那麽多,如何博得她的眼光,就要懂得重要的先做,透过yield*,也能发现重要任务就先去执行
function* normalThing(i){
    
    
    yield "帮我做OX";
    yield "帮QQ";
    
    //先做重要的事情
    yield* moreImportantThing();
    yield "继续做杂事吧";
} 

function* moreImportantThing(i){
    yield "先来接我啦";
}
let controlWay = normalThing();
controlWay.next();


结果是不是如你所想呢?

-- to be continued --


那今天就到这边搂!今天分享喜欢的歌是:
Bruno Mars - The Lazy Song (Official Music Video)
https://www.youtube.com/watch?v=fLexgOxsZu0

每天的休息,是为了後面的追求,明天见。


reference:

忍者2
[JS] JavaScript Generator 的使用


<<:  初学者跪着学JavaScript Day15 : 阵列中没被定义的空值(empty item)

>>:  D30 - 如何看自己需要哪篇 Apps Script 的功能?三十天 Apps Script 旅程的总整理

DAY 15 处理接收到的LINE emoji讯息

我这边群组团购讯息会用到很多LINE emoji,这边会将讯息跟LINE emoji做处理 前面Da...

LiteX/VexRiscv 简介与使用 (二点五) 天地分隔

没想竟然遇到连载途中的除错困境XD 不过30天铁人赛对笔者来说就像黑客松纪录簿,也当作给作软硬整合开...

例行监督表单撰写实务

上一篇内部稽核讲到 5. 监督作业:进行下列监督作业,以确定本制度之有效性、及时性及确实性: (1)...

[Day9] 14 Must Know Dev Tools Tricks

[Day9] 14 Must Know Dev Tools Tricks 14个必须知道的开发工具技...

D16 - 彭彭的课程# Python Module 模组的载入与使用(1)

今天又迎来周末了~ 真是很棒祝大家周末愉快 btw 10/1 流感疫苗开打家里有65岁以上的人可以去...