Promise,generator,async和await,callback 事件循环机制

1、回调函数:

回调函数就是一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数。这个过程就叫做回调。

function a(callback){
   alert("这是first函数a");
   var x =1;
   var y=2;
  return callback(x,y);
 }
 function b(x,y){
   alert("这是回调函数b");
   return x+y;
 }
 $(function(){
   var result = a(b);
   alert("result = "+ result);
 });
//这是first函数a,这是回调函数bresult = 3

//这里函数首先执行了first函数a,之后调用了回调函数b,最后返回函数a的返回值。

回调种类:同步回调、异步回调

回调可以是同步的

function a(fn) {
  fn();
};

a(funtion() {
  console.log('I am callback, but not async'); // step1
});
console.log(end);// step2

回调缺点:

  1. 高耦合,维护困难,回调地狱;
  2. 每个任务只能指定一个回调函数;
  3. 如果几个异步操作之间并没有顺序之分,同样也要等待上一个操作执行结束再进行下一个操作。

 2、promise

ES6给我们提供了一个原生的构造函数Promise,Promise代表了一个异步操作,可以将异步对象和回调函数脱离开来,通过.then方法在这个异步操作上绑定回调函数,Promise可以让我们通过链式调用的方法去解决回调嵌套的问题,而且由于promise.all这样的方法存在,可以让同时执行多个操作变得简单。

promise对象存在三种状态:

  1. Fulfilled:成功状态
  2. Rejected:失败状态
  3. Pending:既不是成功也不是失败状态,可以理解为进行中状态

Promise的缺点:

  1. 当处于未完成状态时,无法确定目前处于哪一阶段。
  2. 如果不设置回调函数,Promise内部的错误不会反映到外部。(resolve就是回调函数)
  3. 无法取消Promise,一旦新建它就会立即执行,无法中途取消。

promise的all,数组中三个数,其中两个正常,一个会报错,怎么让正常的两个返回

由于Promise.all(request).then(…).catch(…) 会在所有requestresolve时才会进then方法,并且把所
有结果以一个数组返回,只要有一个失败,就会进catch。而如果在单个请求中定义了catch方法,那么就
不会进Promise.allcatch方法。因此,可以在单个的catch中对失败的promise请求做处理,可以使
成功的请求正常返回。

 ①Promise then reject了,后面的catch会执行吗?(会)②Promise Catch后面的then还是会执行?(会)

catch()是then()的语法糖。then()返回的是一个promise。 因为then()和catch()又返回了一个promise,因此,后续调用可以串联起来。then()的两个参数函数中返回的值,会自动包装成一个已resolved的promise。

function test(res) {
    return Promise.resolve(res)
        .then(res => {
            console.log(res += '!');
            return res;
        })
        .then(res => {
            console.log(res += '!');
            return Promise.reject("end"); //此处返回了一个新的promise
        })
        .catch(res => {
            console.log(res);
            return res;  //此处也返回了一个新的resolved的promise
        })
        .then(res => {
            console.log(res += '!');  //肯定会执行了
        });
}
test('hello');

 

function test(res) {
   //创建一个rejected状态的Promise
    return Promise.reject(res)
      .then(res => {   //此处不会执行!!!
            console.log(res += '!');
            return res;
        })
        .catch(res => {
            console.log(res);
            return res;  //catch执行完后,返回了一个新的Fulfilled的状态的Promise,
//等同于return Promise.resolve(res);所以后面的then会执行,而catch就不会执行了。
        })
        .then(res => {
            console.log(res += '!');  
        }) 
        .catch(res => {
            console.log(res+"?");
            return res;  
        });
}
test('hello').then((res) =>{
   //test方法中将错误统一栏截处理了,可以不返回内容,
   //然后此处判断res来确定要不要执行!!
});

 可以将非函数参数传递给Promise.then()而不会导致错误?

将非函数参数传递给Promise.then()不会导致错误,then(不是回调函数)也不会进入微任务队列,直接执行(同步)

3、 generator原理

Generator 函数是一个状态机,封装了多个内部状态。执行 Generator 函数会返回一个遍历器对象,可以依次遍历 Generator 函数内部的每一个状态,但是只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield表达式就是暂停标志。

必须调用遍历器对象的next方法,使得指针移向下一个状态。也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句,如果没有return语句,就执行到函数结束)为止。yield表达式是暂停执行的标记,而next方法可以恢复执行。

function* gen(x) {
  console.log('start')
  const y = yield x * 2
  return y
}

const g = gen(1)
g.next()   // start { value: 2, done: false }
g.next(4)  // { value: 4, done: true }

 

  • gen()​ 不会立即执行,而是一上来就暂停,返回一个 ​Iterator ​对象(具体可以参考 Iterator遍历器
  • 每次​ g.next() ​都会打破暂停状态去执行,直到遇到下一个​ yield ​或者 ​return​
  • 遇到​ yield ​时,会执行 ​yeild​ 后面的表达式,并返回执行之后的值,然后再次进入暂停状态,此时​ done: false​。
  • ​next​ 函数可以接受参数,作为上个阶段异步任务的返回结果,被函数体内的变量接收
  • 遇到​ return ​时,会返回值,执行结束,即 ​done: true​
  • 每次​ g.next() ​的返回值永远都是 ​{value: ... , done: ...} ​的形式

如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。

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

 Generator函数暂停恢复执行原理:协程、执行器(Generator 是一个异步操作的容器。它的自动执行需要一种机制,当异步操作有了结果,能够自动交回执行权。

4、async和await

await后面的表达式是从右到左运行的。await针对所跟不同表达式的处理方式:

  • Promise 对象:await 会暂停执行,等待 Promise 对象 resolve,然后恢复 async 函数的执行并返回解析值。
  • 非 Promise 对象:直接返回对应的值。

async 函数执行时,如果遇到 await 就会先暂停执行 ,等到触发的异步操作完成后,恢复 async 函数的执行并返回解析值。为什么会暂停执行,原理是什么?

async/await

async 是Generator函数的语法糖,并对Generator函数进行了改进,是对 yield 的简单封装

async函数对 Generator 函数的改进,体现在以下四点:

  1. 内置执行器。Generator 函数的执行必须依靠执行器,而 async 函数自带执行器,无需手动执行 next() 方法。

  2. 更好的语义。async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。

  3. 更广的适用性。co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)。

  4. 返回值是 Promise。async 函数返回值是 Promise 对象,比 Generator 函数返回的 Iterator 对象方便,可以直接使用 then() 方法进行调用。

 重点是自带了执行器,相当于把我们要额外做的(写执行器/依赖co模块)都封装了在内部

await后面的函数执行完毕时,await会产生一个微任务(Promise.then是微任务)。但是我们要注意这个微任务产生的时机,它是执行完await之后,直接跳出async函数,执行其他代码。其他代码执行完毕后,再回到async函数去执行剩下的代码,然后把await后面的代码注册到微任务队列当中

五、事件循环机制,两者有区别:

浏览器环境下:当主代码微任务执行完毕,开始执行宏任务,这时宏任务中有微任务时,会马上执行微任务再执行其他的宏任务。

nodejs:当宏任务中有微任务时,会先将微任务放到微任务队列中,执行完宏任务再执行微任务。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值