<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<button type="button">读取文件</button>
<input type="file" id="fileinput" multiple />
<output id="outputfile"></output>
<script type="text/javascript">
let fi=document.getElementById("fileinput");
let output=document.getElementById("outputfile");
let reader;
function readfile(file,cb){
// var file=files[0];//获取上传的文件
reader=new FileReader();//
reader.readAsText(file);//读取文本
reader.onload=function(e){
//这个事件发生,意味着数据准备好了
output.textContent=e.target.result;//将结果显示在标签里面
};
reader.onloadend=cb;
}
document.querySelector("button").onclick=function (){
run(go);
}
function run(fn){
let gen=fn();
function next(err,data){
let result=gen.next(data);
if(result.done) return;
setTimeout(() => {
result.value(next);
},5000)
}
next();
}
let ft=thunkify(readfile);
function *go(){
for(let i=0;i<fi.files.length;i++){
yield ft(fi.files[i]);
}
}
function thunkify(fn){
return function(){
let args=new Array(arguments.length);
let ctx=this;
for(let i=0;i < args.length; ++ i){
args[i] = arguments[i];
}
return function(done){
let called;
args.push(function(){
if(called) return;
called=true;
done.apply(null,arguments);
})
try{
fn.apply(ctx,args);
}catch(e){
//TODO handle the exception
done(err);
}
}
}
}
</script>
</body>
</html>
/*
//thunkify是如何运行的呢?
// 接收一个函数f1,然后又返回一个函数f2,在这个f2中,先获取f1中参数,将这个参数保存在args中,
// 然后用这个ctx保证this为f2函数,再返回f3函数,这个函数接收一个回调函数done。在f3中,定义
// called来判断done是否被执行过,args.push中的匿名函数是用来包裹done的,调用这个函数则直接
// 执行了done(done.apply(null,arguments)就是这一句),并且将called定为true,防止多次执行回调。
// fn.apply(ctx,args);这句话的意思是把f1中的this替换为f2,同时把f2中保存的参数(也就是去掉f1中
// 回调函数之后的参数)传入,就等同于f1获取了全部参数,开始运行了
//我觉得可以这么理解,f2就是一个壳子,里面装有f1中除了回调函数这个参数之外的参数,然后这个壳子又
//产生了另一个壳子f3,这个f3里面装了回调函数这个参数。当f3有了这个参数之后,圆满了。然后f3将这个回调
// 参数传给f2,f2又将全部参数传给f1,f1有了全部参数后可以运行了
// 参数进过层层剥离,实现了参数可分次输入的效果,这样就可以在有需要的时候再执行操作
// 可能表述不太清楚,可以试试简单版本的
//Thunk函数简单实现==>只能将2个参数变为单参数
// const Thunk=function(fn){
// return function(...args){
// return function(callback){
// return fn.call(this,...args,callback);
// }
// }
// }
// function f(a,cb){
// cb(a);
// }
// const ft=Thunk(f);
// ft(1)(console.log);
// let one=ft(1);
// let two=one(console.log);
//然后 run函数是如何运行的呢?
// 这个例子有点特别,就是这个回调函数就是本身,即这是个递归函数
// readfile接收两个参数,第一个是文件名,第二个是这个函数本身,这个本身又接收两个参数,第一个是
// 文件名......一直循环下去,直到不再传入回调函数为止,所以只需要一直传入文件名就可以,最后当不再传入
//文件名时即为停止
// 第一个next运行(第一个next参数被默认丢弃),返回对象的value属性的值是f2(ft(fi.files[i])是一个函数),
// 隔了5S,给这个f2传了参数(next函数),即执行,打印出第一个文件内容。然后一直这样循环下去,最后当yield不再
//产出f2时(就是文件名已经被全都输入了一遍),next方法返回对象的done为true,停止运行
*/
有什么不对的地方可以一起交流
喜欢的朋友可以点个赞啊
求关注一下我的公众号,谢谢啦