69生成器函数与异步请求

一、生成器函数
(1)function \*name(param, param, ...) { statements }这种声明方式会定义一个生成器函数,返回一个生成器对象。生成器函数在执行时能暂停,后面又能从暂停处继续执行。
(2)调用一个生成器函数并不会马上执行它里面的语句,而是返回一个这个生成器的迭代器对象。当这个迭代器的 next() 方法被调用时,其内的语句会执行到出现yield的位置为止,yield 后紧跟迭代器要返回的值。如果用的是 yield(多了个星号),则表示将执行权移交给另一个生成器函数(当前生成器暂停执行)。
(3)next()方法返回一个对象,这个对象包含两个属性:value 和 done,value 属性表示本次 yield 表达式的返回值,done 属性为布尔类型,表示生成器后续是否还有 yield 语句,即生成器函数是否已经执行完毕并返回。
(4)调用 next()方法时,如果传入了参数,那么这个参数会作为上一条执行的yield 语句的返回值,例如:
```html:run
function *gen(){
    yield 10;
    y=yield 'foo';
    yield y;
}
var gen_obj=gen();
console.log(gen_obj.next());// 执行 yield 10,返回 10
console.log(gen_obj.next());// 执行 yield 'foo',返回 'foo'
console.log(gen_obj.next(10));// 将 10 赋给上一条 yield 'foo' 的左值,即执行 y=10,返回 10
console.log(gen_obj.next());// 执行完毕,value 为 undefined,done 为 true
```

(5)当在生成器函数中显式 return 时,会导致生成器立即变为完成状态,即调用 next() 方法返回的对象的 done 为 true。如果 return 后面跟了一个值,那么这个值会作为当前调用 next() 方法返回的 value 值。
```html:run
function* idMaker(){
    var index = 0;
    while(index<3)
        yield index++;
}
var gen = idMaker();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // undefined
```

yield\*的示例
```html:run
function* anotherGenerator(i) {
    yield i + 1;
    yield i + 2;
    yield i + 3;
}
function* generator(i){
    yield i;
    yield* anotherGenerator(i);// 移交执行权
    yield i + 10;
}
var gen = generator(10);
console.log(gen.next().value); // 10
console.log(gen.next().value); // 11
console.log(gen.next().value); // 12
console.log(gen.next().value); // 13
console.log(gen.next().value); // 20
```

传递参数
```html:run
function* logGenerator() {
    console.log(0);
    console.log(yield);
    console.log(yield);
    console.log(yield);
}
var gen = logGenerator();
gen.next();// 0
gen.next('pretzel'); // pretzel
gen.next('california'); // california
gen.next('mayonnaise'); // mayonnaise
```

显式返回
```html:run
function* yieldAndReturn() {
    yield "Y";
    return "R";//显式返回处,可以观察到 done 也立即变为了 true
    yield "unreachable";// 不会被执行了
}
var gen = yieldAndReturn()
console.log(gen.next()); // { value: "Y", done: false }
console.log(gen.next()); // { value: "R", done: true }
console.log(gen.next()); // { value: undefined, done: true }
```

生成器函数不能当构造器使用
```html:run
function* f() {}
var obj = new f; // throws "TypeError: f is not a constructor"
来源:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/function*

```
二、副作用函数之处理异步请求:
1、	在 reducers 中的所有操作都是同步的并且是纯粹的,即 reducer 都是纯函数,纯函数是指一个函数的返回结果只依赖于它的参数,并且在执行过程中不会对外部产生副作用,即给它传什么,就吐出什么。
2、	但是在实际的应用开发中,我们希望做一些异步的(如Ajax请求)且不纯粹的操作(如改变外部的状态),这些在函数式编程范式中被称为“副作用”。
3、	Redux 的作者将这些副作用的处理通过提供中间件的方式让开发者自行选择进行实现。redux-thunk 和 redux-saga 是 redux 应用中最常用的两种异步流处理方式。
4、	redux-thunk :从 UI 组件直接触发任务。它的主要思想是扩展 action,使得 action 从一个对象变成一个函数。redux-thunk 的缺点:
(1)action 虽然扩展了,但因此变得复杂,后期可维护性降低;
(2)thunks 内部测试逻辑比较困难,需要mock所有的触发函数;
(3)协调并发任务比较困难,当自己的 action 调用了别人的 action,别人的 action 发生改动,则需要自己主动修改;
(4)业务逻辑会散布在不同的地方:启动的模块,组件以及thunks内部。
5、	redux-saga :采用 Generator 函数来 yield Effects(包含指令的文本对象)。Generator 函数的作用是可以暂停执行,再次执行的时候从上次暂停的地方继续执行。redux-saga 的优点:
(1)声明式 Effects:所有的操作以JavaScript对象的方式被 yield,并被 middleware 执行。使得在 saga 内部测试变得更加容易,可以通过简单地遍历 Generator 并在 yield 后的成功值上面做一个 deepEqual 测试。
(2)高级的异步控制流以及并发管理:可以使用简单的同步方式描述异步流,并通过 fork 实现并发任务。
(3)架构上的优势:将所有的异步流程控制都移入到了 sagas,UI 组件不用执行业务逻辑,只需 dispatch action 就行,增强组件复用性。
来源:https://www.jianshu.com/p/e84493c7af35

三、原生ajax
```html:run
<script charset="utf-8" type="text/javascript">
    var xhr = new XMLHttpRequest;
    console.log(xhr.readyState);//->0
    xhr.open('GET', 'note.txt?_=' + Math.random());
    console.log(xhr.readyState);//->1
    xhr.setRequestHeader('zhufeng','zhufengpeixun');
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 2) {
            console.log(new Date(xhr.getResponseHeader('Date')));
            //->在状态为2的时候获取服务器的时间,并且把获取的结果转换成北京时间;
            // 在2的时候获取可以减少时间差。
        }
        if (xhr.readyState === 4) {
            console.log(xhr.responseText);
        }
        console.log(xhr.readyState);//->2 3 4
    };
    xhr.send(null);
</script>
```

四、fetch
1、fetch的基本使用
fetch是全局量window的一个方法,第一个参数是URL(必须),第二个参数是options(可选),使用Promises来处理结果
```html:run
fetch('/some/url',{
    method:'get'
}).then(function(returnedValue){
    //...执行成功,第2步...
}).catch(function(err){
    //中途任何地方出错...在此处理:(
});
```

2、Request简介
Request对象表示一次fetch调用的请求信息。传入Request参数来调用fetch,可以执行很多自定义请求的高级用法,Request的示例如下:
```html:run
var request=newRequest('/users.json',{
    method:'POST',
    mode:'cors',
    redirect:'follow',
    headers:newHeaders({
        'Content-Type':'text/plain'
    })
});
```

fetch(request).then(function(){}),在Request对象创建完成之后,所有的属性都变为只读属性.请注意,Request有一个很重要的clone方法,特别是在ServiceWorkerAPI中使用时——一个Request就代表一串流(stream),如果想要传递给另一个fetch方法,则需要进行克隆。
来源:http://blog.csdn.net/renfufei/article/details/51494396

3、Response简介
Response代表响应,fetch的then方法接收一个Response实例,也可以手动创建Response对象letmyResponse=newResponse(body,init);
(1)body可选,一个定义response中body的对象.可以是其中一个:Blob、BufferSource、FormData、URLSearchParams、USVString。
(2)init可选。
Response的示例如下:
```html:run
varmyBlob=newBlob();
varinit={"status":200,"statusText":"SuperSmashingGreat!"};
varmyResponse=newResponse(myBlob,init);
```

来源:https://developer.mozilla.org/zh-CN/docs/Web/API/Response/Response

五、Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。它的特征有:
(1)从浏览器中创建 XMLHttpRequests
(2)从 node.js 创建 http 请求
(3)支持 Promise API
(4)拦截请求和响应
(5)转换请求数据和响应数据
(6)取消请求
(7)自动转换 JSON 数据
(8)客户端支持防御 XSRF
来源:https://www.kancloud.cn/yunye/axios/234845


附一、Symbol
ES5 的对象属性名都是字符串,这容易造成属性名的冲突。为了保证每个属性的名字都是独一无二的,从根本上防止属性名的冲突。ES6 引入Symbol,Symbol是 ES6的第七种数据类型,前六种是:undefined、null、Boolean、String、Number、Object。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的。
```html
// 没有参数的情况
let s1 = Symbol();
let s2 = Symbol();
s1 === s2 // false
// 有参数的情况
let s1 = Symbol('foo');
let s2 = Symbol('foo');
s1 === s2 // false
```
来源:http://es6.ruanyifeng.com/#docs/symbol


猜你喜欢

转载自blog.csdn.net/bao13716164418/article/details/91975626
今日推荐