博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Func-Chain.js 另一种思路的javascript异步编程解决方案
阅读量:5320 次
发布时间:2019-06-14

本文共 4832 字,大约阅读时间需要 16 分钟。

本文转载自:https://www.ctolib.com/panruiplay-func-chain.html

Func-Chain.js
另一种思路的javascript异步编程,用于解决老式的回调地狱书写方式
前言
以前在JavaScript中,我们经常通过回调来实现异步逻辑,一旦嵌套层级多了,代码结构就容易变得很不直观,最后成为金字塔形状并且结尾带了一大堆})
后来慢慢有了Promise,generator,async/await的解决方式,但是仍然有许多老的库和函数使用的是回调形式的方法。
例如node.js中大部分api,本工具的作用是为回调形式的函数提供一种链式调用的方法
安装
使用npm

npm install func-chain
let Chain=require('func-chain');import Chain from 'func-chain'

使用 script:

基本使用

假设现在有3个异步任务,需要按一定的顺序执行

// setTimeout模拟的3个异步函数function ajax1(cb) {    console.log('ajax1 start')    setTimeout(function () {        console.log('ajax1 end')        cb && cb()    }, 1000)}function ajax2(cb) {    console.log('ajax2 start')    setTimeout(function () {        console.log('ajax2 end')        cb && cb()    }, 1000)}function ajax3(cb) {    console.log('ajax3 start')    setTimeout(function () {        console.log('ajax3 end')        cb && cb()    }, 1000)}// 表达式语法Chain() > ajax1 > ajax2 > ajax3 > ajax2 > ajax1 || Chain.go()// 也可以使用如下标准语法// new Chain(ajax1, ajax2, ajax3, ajax2, ajax1).go()

使用预期的参数

假设HTML结构如下

jquery封装一个简单的函数

/** * 在随机时间内隐藏目标元素 * @param target 目标元素选择器 * @param cb 回调函数 */function hideDiv(target, cb) {    $(target).hide(Math.random() * 1000, cb)}

我们让多个div按顺序隐藏

// 表达式语法Chain()> hideDiv.args('.div1')> hideDiv.args('.div2')> hideDiv.args('.div3')> hideDiv.args('.div4')> hideDiv.args('.div5')> hideDiv.args('.div6')|| Chain.go()
// 标准语法var chain = new Chain()for(var i = 1; i <= 6; i++) {    chain.add(hideDiv.args('.div' + i))}chain.go()

函数原型上添加了一个args方法,当你执行的函数需要固定的参数的时候,用此方法来设置

一个Node的示例

// node.jslet Chain = require('./dist/func-chain.cjs')let fs = require('fs')Chain()> fs.mkdir.args('testDir')> fs.writeFile.args('testDir/test.txt', 'hello world')> fs.copyFile.args('testDir/test.txt', 'testDir/test2.txt')|| Chain.go()

使用上一级函数传递的参数

// 发送ajax请求数据 | 异步function requestData(url, cb) {    // 假数据    var mockData = url + Math.random()    setTimeout(function () {cb && cb(mockData)}, Math.random() * 1000 + 500)}// 渲染HTML页面 | 同步function renderHTML(data, cb) {    // 计数    renderHTML.count = renderHTML.count + 1 || 1    document.getElementsByTagName('body')[0].innerHTML += data + '
' cb && cb(renderHTML.count)}// 做一些其它的异步或者同步的事情// 函数链中最后一个函数可以不用callbackfunction other(count, cb) { console.log('渲染了' + count + '次') cb && cb()}var chain = Chain() > requestData > renderHTML > other || Chain.end()// cgo()在结尾的时候会默认执行一次, cend()不会chain.go('百度')chain.go('网易')chain.go('新浪')// 任务链可复用,多次调用互不冲突// go()方法中的参数会传递给函数链中第一个方法

函数链对象

创建一个函数链对象

var c1 = new Chain(func1, func2, func3)var c2 = Chain() > func1 > func2 > func3 || Chain.end()var c3 = Chain() > func1 > func2 > func3 || Chain.go()  // 会立即执行一次

上面两条语句都是创建了一个函数链对象,并且包含了3个函数节点

函数链要求每一个函数节点都必须是一个带回调函数的方法,并且函数最后一个参数是回调函数,如下面这种

function fun(x,y,cb) {    // 做点什么    console.log(x)    console.log(y)    cb && cb()}

函数链对象方法

go()
函数链执行go方法时,向go方法传递的参数到被转到函数链中第一个方法,并且会自动追加一个next函数对象,即回调函数

Chain() > function(a,b,next){    console.log(a)  //1    console.log(b)  //2    console.log(next) // function next(){/*...*/}}|| Chain.go(1,2)

调用传入的next方法后会自己进入到下一个函数节点,同时调用next时传递的参数也会被作为下一个函数的实参

Chain()> function(a,b,next){    console.log(a)  //1    console.log(b)  //2    next('a')}> function(a,next) {    console.log(a)  //a    next()}|| Chain.go(1,2)

add()

函数链对象的add方法可以添加函数节点

var c = new Chain()c.add(func1, func2, func3)

函数原型方法扩展

args()
函数原型上添加了一个args方法,你可以用这个方法指定某个函数在执行时要使用的实参

function tmp(a,next) {    console.log(a)    next(a)}new Chain(    tmp,            //4    tmp.args(1),    //1    tmp             //1).go(4)

使用args指定的实参会被优先使用

next对象

自动在末尾传入的next是一个函数对象,上面附加了3个方法

  1. stop() : 执行时立即停止当前函数链
Chain()> function(next){    console.log(1)    next()}> function(next){    console.log(2)     next()}> function(next){    console.log(3)  // 在这里停止了    next.stop() }> function(next){    console.log(4)      next()}|| Chain.go()
  1. skip(number) : 跳过number步
Chain()> function(next){    console.log(1)  // 1    next.skip(2)    // 跳过2步}> function(next){    console.log(2)  // 被跳过    next()}> function(next){    console.log(3)  // 被跳过    next() }> function(next){    console.log(4)  // 4    next()}|| Chain.go()
  1. switchTo(chain, index) : 切换到另一个函数链对象上的第index节点上运行,也可以切换到另一个函数上
var c1 = new Chain(    function(next){         console.log('c1-1')        next()    },    function(next){         console.log('c1-2')        next.switchTo(c2)    })var c2 = new Chain(    function(next){         console.log('c2-1')        next()    },    function(next){         console.log('c2-2')        next()    })c1.go()

switchTo也可以接收一个普通函数,表示切换到目标函数上执行,执行完后停止

关于this
函数在函数链中执行时,this指向当前所在的函数链对象,如果要改变指向,请使用bind

new Chain(    function(next){         console.log(this)   // window        next()    }.bind(window),    function(next){         console.log(this)   // this Chain        next()    }).go()

```js

转载于:https://www.cnblogs.com/smart-girl/p/11462993.html

你可能感兴趣的文章
08: mysql主从原理
查看>>
hibernate分页查询的实现
查看>>
内存加载DLL
查看>>
BFC的布局规则以及触发条件
查看>>
八大排序算法
查看>>
highly variable gene | 高变异基因的选择 | feature selection | 特征选择
查看>>
事件响应模型(游戏引擎、JAVA中等应用)
查看>>
ARM学习笔记14——C语言和汇编相互套用
查看>>
学习笔记1126 - Fib的计算方法,降低了时间复杂度
查看>>
3-8 & 3-9Unicode 编码
查看>>
2016Unite Shanghai 总结
查看>>
zhlan--Python中的字典遍历方法 & 字典取值
查看>>
【iHMI43 4.3寸液晶模块】demo例程(版本1.02)发布
查看>>
【资料下载区】【iCore、 iCore2相关资料】更新日期2017/1/11
查看>>
ResNet,DenseNet
查看>>
我想学前端动画-CSS之transition
查看>>
WiFi攻击的三种方式
查看>>
团队作业4----第一次项目冲刺(Alpha版本)4.29
查看>>
JS 获取当前页面地址 获取当前页面名称
查看>>
[Kafka] - Kafka内核理解:Message
查看>>