javascript异步编程的几种方法?

目前工作中用的比较多的异步模式编程有如下几种方法

一 回调函数

这是异步编程最基本的方法,假设有两个函数f1和f2,后者等待前者的执行结果

f1();
f2();

如果f1是一个很耗时的任务,可以考虑改写f1,把f2写成f1的回调函数

function f1(callback){
   setTimeout(function(){
       // f1的任务代码
      
       //执行回调函数
      callback()
    },1000)
}

执行代码就变成下面这样:

f1(f2);//调用

采用这种方式,我们把同步操作变成了异步操作,f1不会堵塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作推迟执行

具体例子:

由于ajax请求是异步的,有时候我们需要得到ajax请求后的数据,再进行其他的操作,这个时候回调函数会帮我们解决这个问题,具体代码如下:

import $ from 'jquery'
function getData(callback){
  var url="http://xxx.com/activity/v1/homepage/index";
  var data={
      "cityId":110100,
      "type":"coupon"
  }
  $.ajax({
       url:url,
       type:'get',
       dataType:'jsonp',
       jsonp:'callback',
       data:data,
       success:function(resp){
        if(resp.status==200 && resp.data){
            var item = resp.data[0] && resp.data[0].coupon;
            if(callback){
                callback(item) //执行回调函数
            }
        }
       },
       error:function(err){
            console.log("error")
       }
  })
}

function getItem(data){
    if(data){
        //得到数据进行处理
        var url = data.moreUrl;
        alert(url)
    }
}

 getData(getItem) //调用

二 发布/订阅 模式

我们假定,存在一个"信号中心",某个任务执行完成,就向信号中心"发布"(publish)一个信号,其他任务可以向信号中心"订阅"(subscribe)这个信号,从而知道什么时候自己可以开始执行。这就叫做"发布/订阅模式"(publish-subscribe pattern),又称"观察者模式"(observer pattern)。

这个模式有多种实现,下面采用的是Ben Alman的Tiny Pub/Sub,这是jQuery的一个插件。

function PubSub(){
  this.handlers = {};
}

PubSub.prototype = {
  on:function(eventType,handler){
    var self = this;
    if(!(eventType in self.handlers)){
        self.handlers[eventType] = [];
    }
     self.handlers[eventType].push(handler);
      return this;
  },
  trigger:function(eventType){
    var self = this;
    var handlerArgs = Array.prototype.slice.call(arguments,1);
    for(var i=0;i<self.handlers[eventType].length;i++){
      self.handlers[eventType][i].apply(self,handlerArgs)
    }
    return self;
  }
}

具体调用:

var pubsub=new PubSub();

function getData(){
  var url="http://xxx.com/activity/v1/homepage/index";
  var data={
      "cityId":110100,
      "type":"coupon"
  }
  $.ajax({
       url:url,
       type:'get',
       dataType:'jsonp',
       jsonp:'callback',
       data:data,
       success:function(resp){
        if(resp.status==200 && resp.data){
            var item = resp.data[0] && resp.data[0].coupon;
            pubsub.trigger('done',item) //发布事件
        }
       },
       error:function(err){
            console.log("error")
       }
  })
}

//订阅事件
pubsub.on('done',function(data){
  getItem(data)
})

function getItem(data){
  alert('start')
  console.log('data='+data)
    if(data){
        //得到数据进行处理
        var url = data.moreUrl;
        alert(url)
    }
}

 getData() //调用

三 Promise对象

Promise 对象是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口

结合es7提供的async和await使用,代码如下:

import $ from 'jquery'
function getData(){
  return new Promise((resolve,reject) => {
     var url="http://xxx.com/activity/v1/homepage/index";
     var data={
        "cityId":110100,
        "type":"coupon"
      }
      $.ajax({
         url:url,
         type:'get',
         dataType:'jsonp',
         jsonp:'callback',
         data:data,
         success:function(resp){
            if(resp.status==200 && resp.data){
              var item = resp.data[0] && resp.data[0].coupon;
               resolve(item)
            }
         },
         error:function(err){
           reject("error")
         }
      })
  })
}

function getItem(data){
    if(data){
        //得到数据进行处理
        var url = data.moreUrl;
        alert(url)
    }
}

const testAsync = async () => {
  var data = await getData();
  getItem(data); 
}

//调用
testAsync();

参考链接:http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html