promise和generator

promise

JS引擎是单线程的,代码段都是通过JS的异步事件轮询并发模型来执行的。

所谓 Promise,就是一个对象,用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。promise 在于让异步代码看上去同步化。有着更好的可读性Promise是一个构造函数,自身有all、reject、resolve这几个方法,原型上有then、catch等方法。

这里写图片描述

有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。Promise 对象提供统一的接口,使得控制异步操作更加容易。

一个promise的状态必须是可靠并且不可变的,resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数,
resolve是将Promise的状态置为fullfiled,.then用来指定resolve的回调;
reject是将Promise的状态置为rejected,.catch用来指定reject的回调.
all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调,all会把所有异步操作的结果放进一个数组中传给then,并且在一个回调中处理所有的返回数据
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态

async

async模块保证回调只会被触发一次。它同时还为我们处理了错误,管理并行的任务

  • async.waterfall提供瀑布式的流控制。每个操作产生的数据可以传递给下一个函数,通过next这个回调函数
  • async.map允许我们并行对一系列的path调用fs.stat,并把一个结果数组传递给回调函数
  • 最后一步后会调用回调函数cb;如果在整个运行过程中出错了也会调用cb,不会它只会被调用一次

generator

Generator是为JavaScript设计的一种轻量级的协程。它通过yield关键字,可以控制一个函数暂停或者继续执行Generator函数有一个特别的语法function* (),借助这种超能力,我们还可以暂停或者继续执行异步操作,使用像promise或者”thunks”这样的结构来写出看起来像同步的代码。

eg1: generator

function* gen(x){
  var y = yield x + 2; //(3)
  y = yield x + 3;  //(6)
  return y;   //(9)
}

var g=gen(1);  //(1)
console.log(g.next()/*(2)*/); //(4)Object {value: 3, done: false} 
console.log(g.next()/*(5)*/); //(7)Object {value: 4, done: false}
console.log(g.next()/*(8)*/); //(10)Object {value: undefined, done: true}
generator执行步骤如上所示
  • 遇到yield语句,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。协程遇到 yield 命令就暂停,等到执行权返回,再从暂停的地方继续往后执行。它的最大优点,就是代码的写法非常像同步操作

  • 下一次调用next方法时,再继续往下执行,直到遇到下一个yield语句。next 方法的作用是分阶段执行 Generator 函数。每次调用 next 方法,会返回一个对象,表示当前阶段的信息( value 属性和 done 属性)。value 属性是 yield 语句后面表达式的值,表示当前阶段的值;done 属性是一个布尔值,表示 Generator 函数是否执行完毕,即是否还有下一个阶段,false表示函数还没有执行完,只是在这暂停

  • 如果没有再遇到新的yield语句,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。return语句标志着该函数所有有效语句结束,return下方还有多少语句都是无效

  • 如果该函数没有return语句,则返回的对象的value属性值为undefined。

  • Generator函数是分段执行的,yield语句是暂停执行的标记,而next方法可以恢复执行。

eg2: 遍历器互不干扰,作用域独立

function* gen(){
    var i=1;
    yield i++;
    yield i++;
    yield i++;
    return i;
}
var g=gen();
var x=gen();
console.log(g.next());  //Object {value: 1, done: false}
console.log(g.next());  //Object {value: 2, done: false}
console.log(x.next());  //Object {value: 1, done: false}
console.log(g.next());  //Object {value: 3, done: false}

x和g是两个遍历器,从上代码可知,每个遍历器之间互不干扰,作用域独立

eg3: for…of

function* gen(){
    var i=1;
    yield i++;
    yield i++;
    yield i++;
    return i;
}
var g=gen();
for(let i of g){
    console.log(i);  //1,2,3
}

一旦next方法的返回对象的done属性为true,for…of循环就会中止,且不包含该返回对象,所以上面代码不会输出4.

eg4: next()带参数

function* gen(){
    var i=1;
    var a=yield i++;
    console.log(a);   //11
}

var g=gen();
console.log(g.next());  //Object {value: 1, done: false}
console.log(g.next(11));  //Object {value: 2, done: false}

next方法参数的作用,是覆盖掉上一个yield语句的值,带参数跟不带参数的区别是,带参数的情况,首先第一步就是将上一个yield语句重置为参数值,然后再照常执行剩下的语句,通过next方法的参数,就有办法在Generator函数开始运行之后,继续向函数体内部注入值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值