Generator 和 函数异步应用 笔记
function* generator() {
yield 'Owen';
yield 18;
return 'end';
} //调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象 Iterator
let person = generator(); person.next() //{value:'Owen',done:false}
person.next() //{value:18,done:false}
person.next() //{value:'end',done:true}
person.next() //{value:undefined,done:true}
person.next() //{value:undefined,done:true}
yield
- 调用 `next` 遇到 `yield`表达式 暂停执行函数后面的操作,并且 <label> 紧跟 `yield` 后面的表达式的值</label>作为返回对象 `value` 属性的值。
function* g(){
yield 1 + 2
}
let num = g()
num //g {<suspended>}
num.next() //{value:3,done:false}
num.next() //{value:undefined,done:true}
let iter = {};
iter[Symbol.iterator] = function* (){
yield 1;
yield 2;
yield 3;
} [...iter] //[1, 2, 3]
let g = fn();
g.next() //{value:0,done:false}
g.next() //{value:1,done:false}
g.next() //{value:2,done:false}
g.next(1) //{value:0,done:false} function* fn (){
for (let i = 0; true; i++){
let reset = yield i;
if(reset) i = -1;
}
}
function* dataConsumer() {
console.log('Started');
console.log(`1. ${yield}`);
console.log(`2. ${yield}`);
return 'result';
}
let genObj = dataConsumer();
genObj.next();
// Started
//{value: "undefined", done: fales}
genObj.next('a')
//1. a
//{value: "undefined", done: fales}
genObj.next('b')
//2. b
//{value: "result", done: true}
function* fn(){
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
return 6;
} for (let i of fn()){
console.log(i);
//1 2 3 4 5 undefined
} //斐波那契数列 function* fibonacci() {
let [prev, curr] = [0, 1];
for (;;) {
yield curr;
[prev,curr] = [curr, prev + curr];
}
} for (let f of fibonacci()) {
if (f > 1000) break;
console.log(f)
} //遍历任意对象方法 function* objectEntries(obj) {
let propKeys = Reflect.ownKeys(obj); for (let key of propKeys){
yield [key,obj[key]];
}
} let person = {name:'Owen', age:18}; for (let [key,value] of Object.entries(person)){
console.log(key,value);
//name Owen
// age 18
} for (let [key,value] of objectEntries(person)){
console.log(key,value);
//name Owen
// age 18
}
//或者 person[Symbol.interator] = objectEntries for (let [key,value] of person){
console.log(key,value);
//name Owen
// age 18
}
function* g() {
try { yield; } catch (e) {
console.log('内部1',e )
}; try { yield; } catch (e) {
console.log('内部2',e)
};
} let t = g();
t.next(); //{value: undefined, done: false}
try{
t.throw('a');
t.throw('b');
t.throw('c');
} catch(e){
console.log('外部',e)
} //内部1 a
//内部2 b
//外部 c
Generator return
function* g(){
yield 1;
yield 2;
} let ge = g(); ge.next(); // { value: 1, done: false }
ge.return('Owen'); // { value:"Owen", done: true }
ge.next() // { value: undefined, done: true } // try...finally
function* numbers () {
yield 1; try {
yield 2;
yield 3;
} finally {
yield 4;
yield 5;
} yield 6;
}
var nun = numbers();
nun.next() // { value: 1, done: false }
nun.next() // { value: 2, done: false }
nun.return(7) // { value: 4, done: false }
nun.next() // { value: 5, done: false }
nun.next() // { value: 7, done: true }
**next()、throw()、return()**
yield*
//默认
function* f(){
yield 1;
yield 2;
} function* g(){
yield 'x';
f();
yield 'y';
} for(let key of g()){
console.log(key)
//"x" "y"
} //yield* function* y(){
yield 'x';
yield* f();
yield 'y';
} for (let k of y()) {
console.log(k);
// "x" "y" 1 2
} //无 return
function* concat(iter1, iter2) {
yield* iter1;
yield* iter2;
} // 等同于 function* concat(iter1, iter2) {
for (var value of iter1) {
yield value;
}
for (var value of iter2) {
yield value;
}
} // yield* array 如果去掉 * 会返回整个数组
//任何数据结构只要有 Iterator 接口,就可以被yield*遍历。
function* gen(){
yield* ["a", "b", "c"];
}
var g = gen(); g.next() //{value: "a", done: false}
g.next() //{value: "b", done: false}
g.next() //{value: "c", done: false}
g.next() //{value: undefined, done: true} //取出嵌套数组的所有成员
function* iterTree(tree) {
if (Array.isArray(tree)){
for (let arr of tree) {
yield* iterTree(arr)
}
}else{
yield tree
}
} const tree = [1,[2,3],[4,[5,6],7],8]; for (let v of iterTree(tree)){
console.log(v)
}
//1 2 3 4 5 6 7 8 [...iterTree(tree)] //[1, 2, 3, 4, 5, 6, 7, 8] //遍历完全二叉树 // 下面是二叉树的构造函数,
// 三个参数分别是左树、当前节点和右树
function Tree(left, label, right) {
this.left = left;
this.label = label;
this.right = right;
} // 下面是中序(inorder)遍历函数。
// 由于返回的是一个遍历器,所以要用generator函数。
// 函数体内采用递归算法,所以左树和右树要用yield*遍历
function* inorder(t) {
if (t) {
yield* inorder(t.left);
yield t.label;
yield* inorder(t.right);
}
} // 下面生成二叉树
function make(array) {
// 判断是否为叶节点
if (array.length == 1) return new Tree(null, array[0], null);
return new Tree(make(array[0]), array[1], make(array[2]));
}
let tree = make([[['a'], 'b', ['c']], 'd', [['e'], 'f', ['g']]]); // 遍历二叉树
var result = [];
for (let node of inorder(tree)) {
result.push(node);
} result // ['a', 'b', 'c', 'd', 'e', 'f', 'g']
let obj = {
* generator(){ }
}
//or let obj1 = {
generator :function* () {
}
}
```
### Generator 函数的this
> Generator 函数不能和 new 一起使用
> <label>函数总返回一个遍历器,并且它指向 函数实例,同时继承 函数原型对象上的方法</label>
```javascript
function* g() {
this.say = function(){
return 18
};
} g.prototype.say = function () {
return "Owen"
} let obj =g() //g {<suspended>}
obj instanceof g //true
obj.say() //"Owen" obj.next() //{value: undefined, done: true}
obj.say() //"Owen"
//因为 next 返回的是遍历器对象而不是 this 对象,所以不会返回 18 //通过call 绑定this
function* Gen(){
this.age = 18;
yield this.name = "Owen";
}
let obj = Gen.call(Gen.prototype);
obj.next()
obj.age //
obj.next();
obj.name //"Owen" // 使用 new 的变通方法 function G(){
return Gen.call(Gen.prototype)
}
let obj1 = new G();
obj1.next()
obj1.age //
obj1.next();
obj1.name //"Owen"
Generator 函数异步应用
异步编程
$.ajax({
url:'url',
success:function(res){
console.log(res)
}
})
el.addEventListener(event,function(){ },boolean); //IE8 以下
el.attachEvent(event,function(){}) //事件代理委托
var parent = document.getElementById('parent');
parent.addEventListener('click',showColor,false);
function showColor(e){
var son = e.target;
if(son.nodeName.toLowerCase() === 'li'){
console.log('The color is ' + son.innerHTML);
}
}
//实现一个简单的发布订阅
/*
订阅一个事件,发布对应事件并且执行方法
需要先有代理主题 message proxy
然后订阅者去订阅
然后发布者发布消息执行方法
*/ function PubSub () {};
// message proxy
PubSub.prototype.message = {}; // publish
PubSub.prototype.pub = function () {
// Turn arguments into real array
let args = [].slice.call(arguments,0); let event = args.shift(); if(!this.message[event]) return this; let list = this.message[event]; for (let item of list) {
item.apply(this,args);
}
return this;
} // subscribe
PubSub.prototype.sub = function (event,callback){
if( !this.message[event]) {
this.message[event] = [];
} this.message[event].push(callback); return this;
}
// unsubscribe
PubSub.prototype.unsub = function (event) {
if (!this.message[event]) return this; this.message[event] = null;
}
// read I/O
let readFile = require('fs-readfile-promise'); readFile(fileA)
.then( (data) => console.log(data.toString()))
.then( () => readFile(fileB))
.then( (data) => console.log(data.toString()))
.catch((err) => console.log(err));
//example
function* async () {
//... do something
let file = yield readFile(fileA);
//... do something
} //异步操作需要暂停的地方,都用yield语句注明
协程代码的写法非常像同步操作,Generator 函数最大优点是可以交出函数执行权
function* async (num) {
let n;
try{
n = yield ++num;
}catch(err){
console.log(err)
}
return n
}
let g = async(1);
g.next()
g.throw('error');
let fetch = require('node-fetch');
let g = gen();
let result = g.next(); result.value.then((data) => data.json())
.then((data) => g.next(data) ); function* gen() {
let url = '/index.json';
let result = yield fetch(url);
}
//传值
var x = 3;
function fn (x,b) { return x * 3 };
fn(x + 1) // 4 * 3 //传名
fn(x + 1) // (x + 1) * 3
//等同于
var thunk = function (){ return x + 1} fn (thunk) // thunk() * 3
Generator 和 函数异步应用 笔记的更多相关文章
- ES6笔记(5)-- Generator生成器函数
系列文章 -- ES6笔记系列 接触过Ajax请求的会遇到过异步调用的问题,为了保证调用顺序的正确性,一般我们会在回调函数中调用,也有用到一些新的解决方案如Promise相关的技术. 在异步编程中,还 ...
- Generator函数异步应用
转载请注明出处: Generator函数异步应用 上一篇文章详细的介绍了Generator函数的语法,这篇文章来说一下如何使用Generator函数来实现异步编程. 或许用Generator函数来实现 ...
- javascript异步编程之generator(生成器函数)与asnyc/await语法糖
Generator 异步方案 相比于传统回调函数的方式处理异步调用,Promise最大的优势就是可以链式调用解决回调嵌套的问题.但是这样写依然会有大量的回调函数,虽然他们之间没有嵌套,但是还是没有达到 ...
- Generator生成器函数
接触过Ajax请求的会遇到过异步调用的问题,为了保证调用顺序的正确性,一般我们会在回调函数中调用,也有用到一些新的解决方案如Promise相关的技术. 在异步编程中,还有一种常用的解决方案,它就是Ge ...
- .Generator与其他异步处理方案
1.Generator与其他异步处理方案 以前,异步编程的方法,大概有下面四种. 1.1 回调函数 JavaScript 语言对异步编程的实现,就是回调函数.所谓回调函数,就是把任务的第二段单独写在一 ...
- 取代Promise的Generator生成器函数
接触过Ajax请求的会遇到过异步调用的问题,为了保证调用顺序的正确性,一般我们会在回调函数中调用,也有用到一些新的解决方案如Promise相关的技术. 在异步编程中,还有一种常用的解决方案,它就是Ge ...
- Hive自定义函数的学习笔记(1)
前言: hive本身提供了丰富的函数集, 有普通函数(求平方sqrt), 聚合函数(求和sum), 以及表生成函数(explode, json_tuple)等等. 但不是所有的业务需求都能涉及和覆盖到 ...
- jquery ajax success 函数 异步调用方法中不能给全局变量赋值的原因及解决办法
jquery ajax success 函数 异步调用方法中不能给全局变量赋值的原因及解决办法 在调用一个jquery的ajax方法时我们有时会需要该方法返回一个值或者给某个全局变量赋值,可是我们 ...
- ES6新特性三: Generator(生成器)函数详解
本文实例讲述了ES6新特性三: Generator(生成器)函数.分享给大家供大家参考,具体如下: 1. 简介 ① 理解:可以把它理解成一个函数的内部状态的遍历器,每调用一次,函数的内部状态发生一次改 ...
随机推荐
- VMware vs openStack对比直观优势
openStack VS VMware直观优势:1.openStack设计架构开放.生态稳定 大型国际巨头公司支持及开发参与,功能版本迭代快,相对的VMware则是封闭的商业化系统.2.基于openS ...
- posix 正则库程序
使用的是posix 正则库,参考: http://see.xidian.edu.cn/cpp/html/1428.html 执行匹配的时: gcc myreg.c ip.pat 内容: ip.*[0- ...
- MySQL写入中文乱码
这点确实很迷,我的数据库属性确实设置了utf-8字符集,但写入中文还是乱码,后来是直接修改了全局配置才修改过来. 1.进入MySQL的本地安装路径,我的安装路径是"C:\Program Fi ...
- Python服务Debian打包新思路
此文已由作者张耕源授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Debian 打包一直是比较冷僻的技术,大部分同学都不会接触到它. 但是我们 Debian 服务器上安装的各 ...
- E20190419-hm
diagram n. 图表; 示意图; 图解; [数] 线图; contingency n. 意外事故,偶发事件; 可能性,偶然性; [审计] 意外开支; crash v. 碰撞; 使发出巨响; 暴跌 ...
- Git 时光穿梭鸡 撤销修改
工作区内容修改了, 但是并未add到暂存区, 想 回退到上一个版本 在readme.txt中添加了一行: Git is a distributed version control system. Gi ...
- 洛谷P1132 数字生成游戏
P1132 数字生成游戏 题目描述 小明完成了这样一个数字生成游戏,对于一个不包含0的数字s来说,有以下3种生成新的数的规则: 将s的任意两位对换生成新的数字,例如143可以生成314,413,134 ...
- DNS(域名系统)服务器
DNS(Domain Name System),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的Ip数串.通过主机名,最终得到该主机 ...
- [Xcode 实际操作]七、文件与数据-(4 )遍历文件夹中的文件
目录:[Swift]Xcode实际操作 本文将演示如何遍历文件夹下的内容. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKit class V ...
- IT兄弟连 JavaWeb教程 过滤器与监听器经典面试题
1.谈谈你对Servlet过滤器的理解 过滤器是Servlet2.3规范中定义的一种小型的.可插入的Web组件.用来拦截Servlet容器的请求和响应过程,以便查看.提取客户端和服务器之间正在交换的数 ...