generator、async解决回调地狱

Symbol

ES6数据类型除了 Number 、 String 、 Boolean 、 Object、 null 和 undefined ,还新增了 Symbol

symbol是一种新的数据类型(简单数据类型)

symbold的特点:每一个symbol的值都是独一无二的,可以作为对象属性去用

(1)相同参数 Symbol() 返回的值不相等

let sy = Symbol("kk");
let sy1 = Symbol("kk"); 
alert(sy === sy1);      // false

(2)Symbol 作为对象属性名时不能用.运算符,要用方括号。因为.运算符后面是字符串,所以取到的是字符串 sy 属性,而不是 Symbol 值 sy 属性。

//写法一:
var sy=Symbol("aaa");
var sy1=Symbol("aaa");
var obj={
    [sy]:"valuea",
    [sy1]:"valueb"
}
alert(obj[sy]);	//valuea
alert(obj[sy1]);//valueb

//写法二:
let sy2 = Symbol("key1");
let syObject = {};
syObject[sy2] = "kk";
console.log(syObject);    // {Symbol(key1): "kk"}

generator(生成器函数)解决回调地狱

generator特征:

  1. function关键字与函数名之间有一个 * 号
  2. 函数体内使用yield表达式来遍历状态

generator除了用return,还可以用yield 返回多次, 只要碰到yield,函数执行就会暂停,暂停之后用next方法继续执行

首先创建两个json文件 : a.json   b.json
内容分别为 : {"aa" : "hello"}	{"bb" : "world"}

function * ger(){
    yield js_pro("a.json");
    yield js_pro("b.json");
}
var obj=ger();

obj.next().value.then(res=>{
  	console.log(res);	//{aa : "hello"}
    return obj.next().value;
}).then(res=>{
    console.log(res);	//{bb : "world"}
})

generator调用next方法返回的是一个json,里面的value是yield返回的值,done是这个函数有没有执行完毕

console.log(obj.next());	//{value:Promise,done:false}
console.log(obj.next());	//{value:Promise,done:false}
console.log(obj.next());	//{value:undefined,done:true}

generator生成器生成的是一个迭代器

generator函数跟普通函数的区别: generator函数可以暂停

generator函数和async函数的区别:

  • async函数在等待了之后会自动的继续往后执行
  • generator函数暂停了之后需要手动调用next方法才能继续往后执行

iterator

可迭代对象有:数组、nodeList、字符串、set、map,这些对象都有默认的迭代器和Symbol.iterator属性。

可迭代对象的Symbol.iterator属性可以把可迭代对象变成一个迭代器,就可以去执行next()方法

迭代器的本身是一个对象,这个对象有 next( ) 方法返回结果对象,这个结果对象有下一个返回值 value、迭代完成布尔值 done

var  arr=["a","b","c"];
var obj=arr[Symbol.iterator]();
console.log(obj.next());	//{value:"a",done:false}
console.log(obj.next());	//{value:"b",done:false}
console.log(obj.next());	//{value:"c",done:false}
console.log(obj.next());	//{value:undefined,done:true}

当数据具有Symbol.iterator属性时才可使用 for…of 进行迭代 , 因为 for…of 循环只能循环可迭代对象

async用同步的写法执行异步的操作

async 函数是 Generator 函数的语法糖。使用 关键字 async 来表示,在函数内部使用 await 来表示异步。

async的语法:

  1. async 和 await 关键字搭配使用,async 函数永远返回一个 promise 对象,如果函数里有返回值的话,在这个 async 执行之后的.then方法里能拿到
  2. await 是等待的意思,后面一般跟一个promise对象,await会让后面的promise对象自动执行,执行完成后才会继续执行下一句代码
首先创建三个json文件 : a.json   b.json   c.json
内容分别为 : {"aa" : "hello"}	{"bb" : "world"}	{"cc" : "html"}

function js_pro(url) {
    return new Promise(function (resolve, reject) {
        var xhr = new XMLHttpRequest();
        xhr.open("get", url, true);
        xhr.send();
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                if (xhr.status == 200) {
                    var data = xhr.responseText;
                    resolve(data);
                } else {
                    reject("404");
                }
            }
        }
    })
}
async function fun1(){
    let data1=await js_pro("a.json");	//自动执行
    let data2=await js_pro("b.json");
    let data3=await js_pro("c.json");
	return data3;	//返回promise对象
}
fun1().then(res=>{
    console.log(res);
}).catch(res=>{
	console.log(res);
})
### 前端开发中解决回调地狱的方法 在前端开发中,`回调地狱` 是指当多个异步操作需要按照特定顺序执行时,由于嵌套的回调函数层次过深而导致代码难以阅读和维护。以下是几种常见的解决方案及其特点: #### 使用 Promise 链式调用 Promise 提供了一种更加清晰的方式来处理异步操作链。通过 `.then()` 方法可以将原本嵌套的回调变为线性的结构。 ```javascript new Promise((resolve) => { setTimeout(() => { console.log('1'); resolve(); }, 2000); }).then(() => { return new Promise(resolve => { setTimeout(() => { console.log('2'); resolve(); }, 1000); }); }).then(() => { console.log('3'); }); ``` 这种方式显著改善了代码的可读性,但仍需手动传递 `Promise` 对象并显式调用 `.then()`[^2]。 --- #### 使用 Async/Await 结构化异步代码 Async/Await 是基于 Promise 的更高层抽象,它允许开发者以同步风格编写异步代码,从而进一步提升代码的可读性和可维护性。 ```javascript async function executeInOrder() { await new Promise(resolve => { setTimeout(() => { console.log('1'); resolve(); }, 2000); }); await new Promise(resolve => { setTimeout(() => { console.log('2'); resolve(); }, 1000); }); console.log('3'); } executeInOrder(); ``` 上述代码展示了如何利用 `await` 关键字暂停函数执行,直到对应的 `Promise` 被解析后再继续运行后续逻辑。这种方法不仅消除了回调嵌套,还使错误处理变得更加直观[^1]。 --- #### 利用 Generator 函数 (较少使用) 虽然现代 JavaScript 中更推荐使用 Async/Await,但在某些场景下也可以借助 Generators 和协程实现类似的控制流扁平化效果。 ```javascript function* generatorExample() { yield new Promise(resolve => { setTimeout(() => { console.log('1'); resolve(); }, 2000); }); yield new Promise(resolve => { setTimeout(() => { console.log('2'); resolve(); }, 1000); }); console.log('3'); } function run(generator) { const it = generator(); function go(result) { if (result.done) return; result.value.then(res => go(it.next())); } go(it.next()); } run(generatorExample); ``` 尽管此方法有效,但由于其复杂度较高,在实际项目中并不常见[^3]。 --- ### 总结 为了应对前端开发中的回调地狱问题,可以选择如下替代方案: - **Promises**: 将多级嵌套转换成链条形式; - **Async/Await**: 更加简洁优雅地表达异步流程; - **Generators**(备用选项): 可作为实验性质的技术尝试; 其中,Async/Await 已成为主流实践之一,因其能够提供接近于同步编程体验的同时保持语义上的准确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值