多个异步之间的协作方案

简介: 业务逻辑可能依赖两个通过回调或事件传递

一般而言,事件与侦听器的关系是一对多,但在异步编程中,也会出现事件与侦听器的关系是多对 一的情况,也就是说一个业务逻辑可能依赖两个通过回调或事件传递

AOP 模式

lodash 就有 after,在多少次后执行,私有化预制了 timers 变量。

function after (timers, callback) {
  return function (params) {
    if (--timers === 0) {
      callback()
    }
  }
}

let newFn = after(2, function () {
  console.log('after')
})

newFn()
newFn()

以文件读取为例:

function after (timers, fn) {
  let arr = [];
  return function (data) { //  每次都会触发这个函数
    arr.push(data)
    if (--times === 0) { // 达到目的就触发
      fn(arr)
    }
  }
}

let out = after(2, function (data) {
  // 执行完成的回调
  console.log(data)
})


// 异步都有一个回调
fs.readFile('./a.txt', 'utf8', function (err, data) {
  console.log(data)
  out(data)
})
fs.readFile('./b.txt', 'utf8', function (err, data) {
  console.log(data)
  out(data)
})

发布订阅模式

function Events () {
  this.arr = []
}

Events.prototype.on = function (fn) {
  // 订阅
  this.arr.push(fn)
}

Events.prototype.emit = function (params) {
  this.arr.forEach(function (fn) {
    fn(params)
  })
}

// 多个异步并发靠的都是计数器
let e = new Events();
let arr = []
e.on(function (r) {
  if (arr.length === 2) {
      // 执行完成的回调
    console.log('ok')
  }
})

// 异步都有一个回调
fs.readFile('./a.txt', 'utf8', function (err, data) {
  console.log(data)
  e.emit(data)
})
fs.readFile('./b.txt', 'utf8', function (err, data) {
  console.log(data)
  e.emit(data)
})

Promise/Deferred 模式

let fs = require('fs');

// 实现promise延迟对象,defer
Promise.defer = function () {
  let dfd = {};
  dfd.promise = new Promise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  })
  return dfd
}

// function read () {
//   return new Promise((resolve, reject) => {
//     fs.readFile('./a.txt', 'utf8', (err, data) => {
//       if (!err) resolve(data)
//     })
//   })
// }
// 减少代码嵌套,

function read () {
  let defer = Promise.defer()
  fs.readFile('./a.txt', 'utf8', (err, data) => {
    if (!err) defer.resolve(data)
  })
  return defer.promise
}

read().then((data) => {
  console.log(data)
})

promise 化,将一个方法 promise 化,node 有个库, bluebird。

const fs = require('fs')
let bluebird = require('bluebird')

let read = bluebird.promisify(fs.readFile)

Promise.all([read('./a.txt'), read('./b.txt')]).then(data => {
  console.log(data)
})

function promisify (fn) {
  return function (...args) {
    return new Promise((resolve, reject) => {
      fn(...args, function (err, data) {
        if (!err) resolve(data)
      })
    })
  }
}
相关文章
|
7月前
|
边缘计算 JSON 物联网
解锁业务灵活性:RuleGo规则引擎的高效解耦与实时响应秘籍
RuleGo是一个基于Go语言的轻量级、高性能规则引擎,旨在通过动态规则链和组件化设计,简化复杂系统的业务逻辑管理和实时响应。
解锁业务灵活性:RuleGo规则引擎的高效解耦与实时响应秘籍
|
4月前
|
前端开发 JavaScript API
解锁高效应用构建:Vuex与后端交互的前端状态同步策略,让数据流动如行云流水,紧跟前端开发的热点趋势
【8月更文挑战第27天】本文深入探讨了Vue框架下的前端状态管理库Vuex与后端服务交互时的状态同步策略。通过剖析Vuex的核心机制——状态(State)、变异(Mutation)、动作(Action)及模块(Module),文章展示了如何优雅地将后端数据加载并更新至前端状态中。特别地,借助示例代码解释了Action处理API调用、Mutation更新状态的过程,并介绍了如何通过模块化和命名空间提高状态管理的准确性和时效性。此外,还讨论了组件如何利用`mapState`和`mapActions`简化状态访问与操作的方法。遵循这些策略,开发者可以在构建复杂应用时显著提升性能与用户体验。
50 0
|
5月前
|
API 开发工具 对象存储
在PAI平台上,如何实现不同编程语言任务之间的数据共享?
【7月更文挑战第1天】在PAI平台上,如何实现不同编程语言任务之间的数据共享?
129 58
|
5月前
软件复用问题之复用决策中,业务架构和技术之间有何关系
软件复用问题之复用决策中,业务架构和技术之间有何关系
|
5月前
|
开发者 Windows
三类代码协同模式问题之判断项目的协同规模决定采用集成分支问题如何解决
三类代码协同模式问题之判断项目的协同规模决定采用集成分支问题如何解决
|
5月前
|
存储 数据中心 开发者
交易链路设计原则&模式问题之协调者在系统中的知名度对开发的影响如何解决
交易链路设计原则&模式问题之协调者在系统中的知名度对开发的影响如何解决
|
7月前
|
消息中间件 存储 监控
【ZeroMQ的SUB视角】深入探讨订阅者模式、C++编程实践与底层机制
【ZeroMQ的SUB视角】深入探讨订阅者模式、C++编程实践与底层机制
812 1
|
7月前
|
前端开发
微前端架构:跨越边界的独立协作
在传统的前端开发中,单体应用往往面临代码复杂、维护困难等问题。而微前端架构通过将应用拆分成独立的小型服务,实现了不同团队的独立开发与部署,从而提升了开发效率和可维护性。本文将介绍微前端架构的概念与实践,探讨其在实际项目中的应用场景和优势。
|
缓存 算法 前端开发
协同文档工作机制简介
随着在线办公的兴起,传统办公套件 Office 的在线化需求也随之增加。钉钉文档作为钉钉核心办公套件之一,上线已经三年,其间持续迭代,已成为一个极其复杂的产品。对前端工程师而言,协同文档是一个较为有挑战的领域,除了传统天坑富文本编辑器外,还引入了协同编辑这一挑战,钉钉文档甚至还支持专业排版能力。 来自钉钉的前端技术专家本杰,就在第十六届D2前端技术论坛进行了分享,本次分享以钉钉文档为例,简述协同文档的工作机制。
726 0
协同文档工作机制简介
|
缓存 关系型数据库 PostgreSQL
引入时间概念的分布式系统浅谈
简述分布式系统Clock-SI、clock skew、TSO