如何使用生成器函数,解决回调地狱问题?写出优雅的代码(小白笔记)

在这里,本文都是通过定时来模拟ajax请求.

定义

看一下mnd怎么说的?

生成器函数提供了一个强大的选择:它允许你定义一个包含自有迭代算法的函数, 同时它可以自动维护自己的状态。 生成器函数使用 function*语法编写。 最初调用时,生成器函数不执行任何代码,而是返回一种称为Generator的迭代器。 通过调用生成器的下一个方法消耗值时,Generator函数将执行,直到遇到yield关键字。

怎样写一个生成器呢?

    function* makeRangeIterator(start = 0, end = Infinity, step = 1) {
      for (let i = start; i < end; i += step) {
        yield i;
      }
    }

又是如何调用的呢?

    var a = makeRangeIterator(1, 10, 2)
    console.log(a.next()) // {value: 1, done: false}
    console.log(a.next()) // {value: 3, done: false}
    console.log(a.next()) // {value: 5, done: false}
    console.log(a.next()) // {value: 7, done: false}
    console.log(a.next()) // {value: 9, done: false}
    console.log(a.next()) // {value: undefined, done: true}

它和我们迭代器都差不多,都有一个next方法,每次调用,就只是执行一段代码。返回的也是value和done。

使用场景

先来一个简单的例子:
需求:1秒后,打印111,2秒后打印222,3秒后打印333
原生写法:

    setTimeout(() => {
      console.log(111);
      setTimeout(() => {
        console.log(222);
        setTimeout(() => {
          console.log(333);
        }, 1000)
      }, 1000)
    }, 1000)

这就是我们常说的回调地狱问题了。

使用yiled函数实现

    function one() {
      setTimeout(() => {
        console.log(111);
        b.next()
      }, 1000);
    }
    function two() {
      setTimeout(() => {
        console.log(222);
        b.next()
      }, 1000);
    }
    function three() {
      setTimeout(() => {
        console.log(333);
        b.next()
      }, 1000);
    }
    function* gen() {
      yield one()
      yield two()
      yield three()
    }
    let b = gen()
    b.next()

这样一来我们就能解决回调地狱的问题了。

案例2:
需求:要先拿到用户数据,再通过用户数据去查询订单,最后查询商品
在这里,我们也是用定时器模拟数据获取,并传值的过程

    function getUserData() {
      setTimeout(() => {
        let data = '用户数据'
        iterator.next(data)
      }, 1000);
    }
    function getOrderData(datas) {
      setTimeout(() => {
        let data = '订单数据'
        console.log(datas, 'datas');
        iterator.next(data)
      }, 1000);
    }
    function getShopData() {
      setTimeout(() => {
        let data = '商品数据'
        iterator.next(data)
      }, 1000);
    }
    function* getData() {
      let users = yield getUserData()
      console.log(users);
      let orders = yield getOrderData(users)
      console.log(orders);
      let shops = yield getShopData()
      console.log(shops);
    }
    let iterator = getData()
    iterator.next()

通过这样的方式,我们代码的缩进有头,且不会产生回调地狱问题。
更多知识推荐:
MDN:迭代器和生成器
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Iterators_and_Generators
IBM:详解 ECMAScript 6 中的生成器(Generator)https://developer.ibm.com/zh/languages/javascript/articles/wa-es6-generator

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值