thunkify源码分析:逐步分析
自己实现一个简单的 thunkify 来了解一下原理
个人的结
- Thunk是专业领域大家已知的概念
- 这个是类似于
promise
一类的定制标准的东西,符合这套标准,结合一个run
方法 +generator
,就能轻松实现一套处理异步的语法糖出来 - 我自己曾经也实现过一套类似的东西:afeiship/next-async-queue 也是定义了一套简单的标准,来实现异步
task
的语法糖
先看一下使用
var thunkify = require('thunkify');
var fs = require('fs');
var read = thunkify(fs.readFile);
read('package.json', 'utf8')(function (err, str) {});
实现思路
- 入参:一个函数,且最后一个参数为回调函数
- 2层执行,说明有2层回调
function thunk(fn){
// 原函数的参数部分
return function () {
// 原函数的回调部分
return function (done) {};
};
}
简单的实现(ryf)
var thunk = function(fn){
return function (){
// 1. 获取函数参数(除 callback 部分)
var args = Array.prototype.slice.call(arguments);
return function (callback){
// 2. 将用户的 callback 也加进入
args.push(callback);
// 3. 真实的执行用户 function: fn
return fn.apply(this, args);
}
};
};
有什么用
在没有 for..of 之前,可以自己写一个很简单的 run 方法,来实现 generator 函数 的自执行,从而实现异步流程类似于同步的写法
import $ from 'jquery';
import thunkify from 'thunkify';
function ajax(url, cb) {
$.ajax({
url: url,
success: cb,
});
}
const getData = thunk(ajax);
// 创建 Generator
const gen = function* () {
const data1 = yield getData('https://jsonplaceholder.typicode.com/todos/1');
console.log(data1); // 获取数据后自定义操作
const data2 = yield getData('https://jsonplaceholder.typicode.com/todos/2');
console.log(data2);
const data3 = yield getData('https://jsonplaceholder.typicode.com/todos/3');
console.log(data3);
};
// 自动执行 Generator
function run(fn) {
var g = fn();
function next(data) {
var result = g.next(data);
// 让 result.value 可以接收下一步执行的回调函数,这个就是 Thunk 的意义
if (result.done) return;
result.value(next);
}
next();
}
run(gen);
参考
https://es6.ruanyifeng.com/#docs/generator-async#Thunkify-%E6%A8%A1%E5%9D%97