首页 > 编程语言 > 详细

Javascript异步编程

时间:2020-11-04 21:04:56      阅读:20      评论:0      收藏:0      [点我收藏+]

1:出现异步的原因

JavaScript执行环境是单线程的,所以同一个时间只能执行一次任务,后面任务队列都等待着前一个任务执行完毕才能够执行,为了解决这个问题,Javascript将任务分为同步和异步两种执行模式

2:回调函数处理异步

这是最基本的异步处理方式了

//加入两个函数
f1() ---耗时很长 会阻塞后面代码
f2()

//改写f1
funtion f1(callback){
    setTimeout(function(){
        //f1代码
        callback()
    })
}//执行代码就编程这个样子 f1(f2);

采用这种方式,就可以把同步编程异步操作了,f1不会阻塞任何程序,相当于执行了程序的主要逻辑,但是代码高度耦合,流程会很乱,而且每个人物只能指定一个回调函数

3:事件监听处理

这种方式采用的是事件驱动,这种方式不会考虑代码编写顺序,而是取决于某个时间是否触发。

f1.on(‘done‘,f2);//注册监听
funtioin f1(){
    setTimeout(function(){
        f1.trigger("done") //触发done,执行f2
    })
}

这种方法有点很明显,可以绑定多个事件,每个事件指定多个回调,而且可以去耦合,有利于实现模块化,缺点是过度依赖驱动,事件流程变得不清晰。

4:发布和订阅

上一节的"事件",完全可以理解成"信号"。

我们假定,存在一个"信号中心",某个任务执行完成,就向信号中心"发布"(publish)一个信号,其他任务可以向信号中心"订阅"(subscribe)这个信号,从而知道什么时候自己可以开始执行。这就叫做"发布/订阅模式"(publish-subscribe pattern),又称"观察者模式"(observer pattern)。这个模式有多种实现,下面采用的是Ben Alman的Tiny Pub/Sub,这是jQuery的一个插件。

首先,f2向"信号中心"jQuery订阅"done"信号。

  jQuery.subscribe("done", f2);

然后,f1进行如下改写:

jQuery.subscribe("done", f2); 
function f1(){
    setTimeout(function () {
      // f1的任务代码
      jQuery.publish("done");
    }, 1000);
  }

jQuery.publish("done")的意思是,f1执行完成后,向"信号中心"jQuery发布"done"信号,从而引发f2的执行。

此外,f2完成执行后,也可以取消订阅(unsubscribe)。

  jQuery.unsubscribe("done", f2);

这种方法的性质与"事件监听"类似,但是明显优于后者。因为我们可以通过查看"消息中心",了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行。

5:Promiss对象

这个实例化之后无论成功或者失败,都会返回一个函数供接下来的(then error )等操作使用

new Promiss((resole,reject) => {
    //f1代码
    //成功回调 resolveI(参数) 或者 失败回调 reject(回调)
}).then( () => {
    //接下来操作
})

6:next方法 + promiss

理解next()使用

技术分享图片

总结流程:

(1)执行next后会从上往下依次返回每个yield表达式的值,

(2)如果next有传参的话,会整个覆盖掉将要返回当前yield的上一个yield,

(3)方法内的yield表达式和return都执行完了,就会直接返回undefined了。

入参  分析结果
1  1(无论是否传参,传什么参数,返回第一个表达式的值1)
3  3(返回第二个表达式的值yield a,a=上一个yield表达式yield 1,被参数3覆盖,所以a=3)
4  4(返回第三个表达式的值yield b,b=上一个yield表达式yield a,被参数4覆盖,所以b=4)
5  12(返回return a+b+c,c=上一个yield表达式yield b,被参数5覆盖,所以c=5,也就是a+b+c=3+4+5=12)

这下没错了,太不容易了

解决异步

const fs = require(‘fs‘)
 
// Promise 版的readFile
const readFile = function (fileName) {
 return new Promise(function(resolve, reject) {
  fs.readFile(fileName, function(err, data){
   if (err) return reject(error);
   resolve(data);
  })
 })
}
 
const gen = function * () {
 let f1 = yield readFile(‘a.txt‘);
 let f2 = yield readFile(‘b.txt‘);
 
 console.log(‘F1--->‘, f1.toString());
 console.log(‘F2--->‘, f2.toString());
}
 
 
// 基于 Generator 和 Promise 的自动执行器
function run(gen) {
 
 let g = gen();
  
 function next(data) {
   
  let result = g.next(data);
 
  if (result.done) return result.value;
 
  result.value.then(function(data) {
   next(data);
  });
 }
 next();
}
 
run(gen);

7:基于async和await的异步方式

await 所在的那一行语句是同步的,将会等待当前这一步的执行结果

const fs = require(‘fs‘)
 
// Promise 版的readFile
const readFile = function (fileName) {
 return new Promise(function(resolve, reject) {
  fs.readFile(fileName, function(err, data){
   if (err) return reject(err);
   resolve(data);
  })
 })
}
 
const asyncReadFile = async function () {
 const f1 = await readFile(‘a.txt‘);
 const f2 = await readFile(‘b.txt‘);
 console.log(f1.toString());
 console.log(f2.toString());
};
 
asyncReadFile();

整体是一个异步函数 不难理解。在实现上,我们不妨逆向一下,语言层面让async关键字调用时,在函数执行的末尾强制增加一个promise 反回:内部是同步的 是怎么做到的?实际上 await 调用,是让后边的语句(函数)做了一个递归执行,直到获取到结果并使其 状态 变更,才会 resolve 掉,而只有 resolve 掉,await 那一行代码才算执行完,才继续往下一行执行。

Javascript异步编程

原文:https://www.cnblogs.com/yanzq-x/p/13927510.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!