0304消息订阅与发布_fetch_小结-github搜索案例-react应用

文章目录

    • 1 消息订阅与发布
      • 1.1 消息传递模式
      • 1.2 pubsub-js
      • 1.3 应用改进之前的Github搜索案例
    • 2 fetch发送请求
      • 2.1 前端请求后端数据方式
      • 2.2 github搜索案例fetch版本
    • 3 小结
    • 结语

1 消息订阅与发布

1.1 消息传递模式

消息订阅与发布(Publish/Subscribe)是一种常见的消息传递模式,也称为观察者模式(Observer Pattern)或事件模型(Event Model)。

在该模式中,有两个重要的角色:发布者和订阅者。发布者负责产生消息,并将消息发布到一个或多个主题(Topic)上。订阅者可以订阅一个或多个主题,以接收他们感兴趣的消息。当一个主题上有新消息发布时,所有订阅该主题的订阅者将会收到这个消息。

这种模式的优势在于它能够将发布者和订阅者分离,使得它们之间不需要直接交互。这种松散耦合的设计使得系统更加灵活和可扩展,能够更容易地添加新的发布者和订阅者。同时,它也可以有效地降低系统中的耦合度和复杂性。

常见的消息订阅与发布的实现方式包括使用消息队列(Message Queue)、事件总线(Event Bus)等。这些实现方式都提供了一种可靠、可扩展、高效的消息传递机制,可以在大规模的分布式系统中使用。

1.2 pubsub-js

PubSubJS是一个JavaScript库,用于实现发布/订阅模式的消息传递机制。它提供了一种简单的API,可以方便地实现发布/订阅模式,从而解耦代码和提高代码复用性。

PubSubJS的核心概念是消息通道(channel),消息通道是一个主题(topic),可以将一个或多个订阅者订阅到该主题上。消息通道是由字符串标识的,可以使用任意的字符串作为标识符。

PubSubJS提供了以下API:

  • PubSub.subscribe(channel, subscriber):将一个订阅者订阅到指定的通道上。
  • PubSub.publish(channel, message):向指定的通道发布一个消息。
  • PubSub.unsubscribe(token):取消订阅一个通道。

其中,订阅者是一个回调函数,当有消息发布到该通道时,订阅者会被调用,同时将发布的消息作为参数传递给它。

以下是一个使用PubSubJS的示例代码:

javascriptCopy code
// 订阅一个通道
var subscription = PubSub.subscribe('myChannel', function(msg, data) {
    console.log(msg, data);
});

// 向通道发布一个消息
PubSub.publish('myChannel', 'hello world');

// 取消订阅一个通道
PubSub.unsubscribe(subscription);

上述示例代码中,我们订阅了一个名为“myChannel”的通道,当有消息发布到该通道时,回调函数会被调用并打印出消息和数据。然后,我们发布了一个消息到该通道,并取消了订阅。

总的来说,PubSubJS是一个简单、轻量级的JavaScript库,可以方便地实现发布/订阅模式的消息传递机制,它可以帮助我们实现模块化、松耦合的代码。

1.3 应用改进之前的Github搜索案例

我们之前github搜索案例,数据传递:

  • List组件:使用数据
  • Search组件:生产数据
  • 数据传递通过共同的父组件App传递,非常的麻烦,增加不必要的消耗

改进步骤:

  • 我们把数据放入主要使用的主键List;

  • List组件订阅消息,回调函数更新我们的state数据;

  • Search组件请求后端,发布消息。

List组件修改代码1.3-1如下所示,其他不变:

  state = { 
    githubUsers: [], // 初始化状态,github用户
    isFirst: true, // 是否第一次打开页面
    isLoadign: false, // 数据是否加载中
    err: '', // 存储相关的错误信息
  } 

  componentDidMount() {
    PubSub.subscribe('github-user', (_, data)=> {
      this.setState(data)
    })
  }

Search组件修改代码1.3-2如下所示:

  search = () => {
    // 获取用户输入
    const {keyelement: {value: keyword}} = this
    // console.log(keyword);
    // 发送请求前通知List更新状态
    PubSub.publish('github-user', {isFirst: false, isLoading: true})
    // 发起网络请求
    axios.get(`/api1/search/users?q=${keyword}`).then(
      resp => {
        // console.log('请求成功',resp.data);
        const data = resp.data.items.map(item => {
          return {id: item.id, avatar: item.avatar_url, homePage: item.html_url, username: item.login}
        })
        PubSub.publish('github-user', {isLoading: false, githubUsers: data})
      },
      error => {
        // console.log('请求失败', err);
        PubSub.publish('github-user', {isLoading: false, err: error.message})
      }
    )
  }

2 fetch发送请求

2.1 前端请求后端数据方式

在当前前后端分离的情况下,前端请求数据,浏览器原生支持的API有2种:

  • XmlHttpRequest
  • Fetch

XmlHttpRequest (XHR) 和 Fetch 都是用来发送 HTTP 请求的浏览器原生 API,但是它们之间有以下几点不同:

  1. API 使用方式:XHR 使用回调函数和事件监听的方式来处理异步请求和响应,而 Fetch 使用 Promise API 来处理异步请求和响应,更加简洁明了。
  2. 请求和响应对象:XHR 的请求和响应对象是通过 XHR 实例的属性和方法来获取和设置的,而 Fetch 的请求和响应对象则是通过 Promise API 的返回值来获取的。
  3. 请求和响应处理:XHR 可以通过设置请求头、设置请求体、设置响应类型等方式来处理请求和响应,而 Fetch 则可以通过设置请求选项、设置请求体、设置响应类型等方式来处理请求和响应。
  4. 跨域支持:XHR 可以通过设置 withCredentials 属性来实现跨域请求,而 Fetch 可以通过设置 mode 选项来实现跨域请求。
  5. 错误处理:XHR 可以通过监听错误事件、超时事件等方式来处理请求过程中的错误,而 Fetch 可以通过 catch() 方法来处理请求过程中的错误。

总的来说,XHR 和 Fetch 都是可靠的浏览器原生 HTTP 请求 API,具有各自的优势和适用场景,开发者可以根据具体情况选择适合自己的 API 来发送 HTTP 请求。

相信原生XmlHttpRequest一定给使用过的小伙伴留下了“美好的”回忆,基于XmlHttpRequest开发繁琐,对其做了封装和功能增强的axios库应运而生。axios之前我们通过react脚手架集成和使用过,下面我们来练习下fetch的使用。

2.2 github搜索案例fetch版本

Search组件搜索代码2.2-1如下修改:

  search = async () => {
    // 获取用户输入
    const { keyelement: { value: keyword } } = this
    // console.log(keyword);
    // 发送请求前通知List更新状态
    PubSub.publish('github-user', { isFirst: false, isLoading: true })
    // 发起网络请求
    try {
      const resp = await fetch(`/api1/search/users2?q=${keyword}`)
      let data = await resp.json()
      data = data.items.map(item => {
        return { id: item.id, avatar: item.avatar_url, homePage: item.html_url, username: item.login }
      })
      PubSub.publish('github-user', {isLoading: false, githubUsers: data})
    } catch (error) {
      PubSub.publish('github-user', {isLoading: false, err: error.message})
    }
  }

之前使用axios可以做相应的优化,这里我们不在演示,有兴趣的可以自己试一下。

3 小结

通过github案例,我们做如下总结。

  • 设置状态时要考虑全面,例如带有网络请求的组件,要考虑请求失败怎么处理;

  • ES6:结构赋值+重命名

    let obj = {a:{b:1}}
    const {a} = obj // 传统结构赋值
    const {a:{b}} = obj // 连续结构赋值
    const {a:{b: newName}} = obj // 连续结构赋值+重命名
    
  • 消息订阅与发布

    • 先订阅,在发布;
    • 适用于任意组件通信;
    • 要在组件的ComponentWeillUnmount中取消订阅
  • fetch发送请求(关注分离的设计思想)

    async fun() {
        try {
          const resp = await fetch('rul')
          let data = await resp.json()
          // 业务逻辑
        } catch (error) {
          // 异常处理
        }
      }
    

结语

❓QQ:806797785

⭐️源代码仓库地址:https://github.com/gaogzhen/react-staging.git

参考:

[1]React视频教程[CP/OL].2020-12-15.p71-73.

[2]React官网[CP/OL].

[2]ChatGPT[CP/OL].

你可能感兴趣的:(#,React,github,react.js,javascript,pubsub消息订阅与发布,fetch)