前端学习笔记(5)-ES6中promise、Generator、Module等使用场景

1. Promise

  • 一种异步编程的解决方案,通过一个回调,避免更多的回调

异步编程允许我们在执行一个长时间任务时,程序不需要等待,而是继续执行之后的代码,直到这些任务完成之后再来通知你,通常是以回调函数(callback)的形式,这种编程模式避免程序的阻塞。尤其适用于需要经常进行网络操作,数据库访问的应用。

使用setTimeout()让一个函数在指定事件后执行,如以下例子

setTimeout(function (){
    console.log('执行了回调函数')
},3000)
console.log(111)
 
//    111
//    执行了回调函数

这种不阻塞后面任务执行的任务就叫做异步任务。 

 回调地狱:在回调函数中再嵌套回调函数的情况称为回调地狱(是实现代码顺序执行的一种操作方式)

setTimeout(function(){
    console.log('日日复月月');
    setTimeout(function(){
        console.log('月月复年年');
        setTimeout(function(){
            console.log('年年复此生')
        },1000)
    },2000)
},3000)
 
//    日日复月月
//    月月复年年
//    年年复此生

这种回调函数中嵌套回调函数的情况就叫做回调地狱。回调地狱就是为是实现代码顺序执行而出现的一种操作, 

(1)代码的可读性差、可维护性差

(2)代码的扩展性差

promise解决办法:

可以调用他的.then方法并传递一个回调函数,如果这个请求在未来成功完成,那么回调函数会被调起,请求的结果会以参数的形式传递进来。并且可以使用then链式结构将多个异步操作串联起来,代码向下方增长而非向右,大大提升了可读性

function fn(str){  //str='日日复月月'
    //创建Promise对象
    let p = new Promise(function(resolve,reject){
        let flag = true;
        setTimeout(function(){  //模拟异步调用
            if(flag){  //模拟异步调用成功
                resolve(str)  //将str通过resolve传递出去 ---- resolve('日日复月月')
            }else{  //模拟异步调用失败
                reject("操作失败")  //将失败的信息通过reject传递出去
            }
        })
    })
    return p;
}
 
fn('日日复月月').then((data)=>{  //.then接收resolve(str)传回来的信息
    console.log(data);  //data=('日日复月月')
    return fn('月月复年年');
}).then((data)=>{
    console.log(data);  //data=('月月复年年')
    return fn('年年复此生')
}).then((data)=>{
    console.log(data)  //data=('年年复此生')
}).catch((err)=>{
    console.log(err)
})
 
//    日日复月月
//    月月复年年
//    年年复此生

代码来源:回调函数和回调地狱_Han_Zhou_Z的博客-CSDN博客_回调地狱是什么意思 

  • Promise几乎就是它的字面意思,代表一个承诺,承诺这个请求会在未来某个时刻返回数据,

        async、await他们是基于Promise之上的语法糖,让异步操作更加简单明了,当需要操作异步函数时,使用关键字async关键字将函数标记为异步函数,异步函数返回值为Promise对象,await可以等待promise完成之后返回最终的结果,response就相当于服务器返回的响应数据了。

async function f(){

{

f(),

````````````````````````````````
async function f(){
    const response = await fetch("http://...")
{
//其中fetch也是一个异步函数
f(),

那如何表示异步函数是否完成了呢,Promise 异步操作有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。除了异步操作的结果,任何其他操作都无法改变这个状态。promise的实例可以传入两个参数表示两个状态的回调函数,第一个是resolve,第二个是reject,在promise中我们使用resolved代表fulfilled,使用rejected表示fail。

const p2 = new Promise(function(resolve,reject){  
    resolve('success3'); 
    reject('reject');
});

当异步运行成功时,自然会调用resolve获得最终数据,而失败时调用reject可以传递错误信息等。

1.5 async 和 promise 的写法对比

async function func(){
	return 'hello world'
}
console.log(func())
let p = new Promise((resolve,reject)=>{
	resolve('hello world')
})
console.log(p)

        虽然最后的打印的结果是一样的。但是第二个代码Promise对象的状态已经从pending 变成 fulfilled了,如果在then中抛出一个错误的话,也不会经过错误捕捉操作。从一开始就要决定状态, 然后根据状态去选择执行下一步。使用promise对象,如果第一步没有完成状态的选择,那么不会去执行then中的方法。
        如果使用async的话,如果你在then中不抛出错误的话,它会默认按照fulfilled状态一直执行then中的方法,不会固定为fulfilled状态。只要你某个then方法中抛出错误,那么就直接跳过执行catch方法。
        所以相比之下还是 async要更方便一点。

2.Generator函数

Generator 函数是 ES6 提供的 一种异步编程解决方案,语法行为与传统函数完全不同。

Generator函数有两个特征:

  • function命令与函数名 之间有一个'*'
  • 函数体内部使用 yield语句定义不同的内部状态。

定义:

function* hello() {
	yield "hello";
	yield "world";
	return "done";
}

let h = hello(); // 此时拿到的是一个Generator对象

当调用它的next时 ,才会进入它的方法体,遇到yield,直接返回语句内容 ,并停止执行后面的语句,第二次调用next时 ,会执行下一条yield

例如打印上面定义的 Generator函数变量

console.log(h.next()); //{value:"hello", done: false} 
console.log(h.next()); //{value:"world", done: false}
console.log(h.next()); //{value:"done", done: true}
console.log(h.next()); //{value: undefined, done: true}

原文链接:https://blog.csdn.net/weixin_45525272/article/details/123047831

ES6新特性:Generator函数_杨 戬的博客-CSDN博客_es6 generate

通过执行结果我们可以看到,通过hello()返回的h对象,每调用一次next()方法返回一个对象,该对象包含了value值和done状态。

直到遇到return关键字或者函数执行完毕,这个时候返回的状态为ture,表示已经执行结束了。

应用场景

 控制流管理:

上面Promise的例子将回调地狱的例子优化,把回调函数,改成了直线执行的形式,但是加入了大量 Promise 的语法。Generator 函数可以进一步改善代码运行流程。

function* longRunningTask(value1) {
  try {
    var value2 = yield step1(value1);
    var value3 = yield step2(value2);
    var value4 = yield step3(value3);
    var value5 = yield step4(value4);
    // Do something with value4
  } catch (e) {
    // Handle any error from step1 through step4
  }
}

原文链接:https://blog.csdn.net/weixin_43964148/article/details/106878215

然后,使用一个函数,按次序自动执行所有步骤。 

scheduler(longRunningTask(initialValue));

function scheduler(task) {
  var taskObj = task.next(task.value);
  // 如果Generator函数未结束,就继续调用
  if (!taskObj.done) {
    task.value = taskObj.value
    scheduler(task);
  }
}

 控制流管理:保证代码的顺序直线进行,不方便在于不能自动执行,流管理 比promise更方便

3.Module(模块化)

模块化就是将js文件分解为各个功能不同的js文件,每一个js文件就是一个独立的模块,每一个模块就对应界面上的一个部分,但是模块化管理,很多的数据要进行共享,就需要遵守一个规范,现在的标准的规范就是ES6

在node.js中遵循的是CommonJS的模块化规范,其中:

  • 导入其他模块中使用require()方法
  • 模块对外共享成员使用module.exports对象

模块化的好处就是模块化和规范化,降低沟通的成本,方便各模块的相互调用; 比如像导航栏就可以单独弄成一个小的模块,这样就可以复用
在ES6模块化规范之前,还有其他的各种各样的模块,AMD和CMD等,但是这些小的规范都是局限的,而ES6模块化的出现就解决了杂乱,直接统一进行管理。

ES6模块化规范是浏览器端和服务器端 的通用的模块化开发规范。在其中定义了:

  • 每一个js文件都是一个独立的模块
  • 导入其他的模块的成员使用import关键字
  • 向外共享模块成员使用export关键字

ES6模块化主要包含3中用法:

  • 默认导出与默认导入
  • 按需导出与按需导入
  • 直接导入并执行模块中的代码
     

猜你喜欢

转载自blog.csdn.net/JiangZhengyang7/article/details/127865769