看了这篇文章,让你不在害怕前端方法异步的问题

1.同步API与异步API

同步API:只有当前API执行完成后,才能继续执行下一个API;

异步API:当前API的执行不会阻塞后续代码的执行;

区别:
①同步API可以从返回值中拿到API执行的结果,但是异步API不可以。
②代码执行顺序不同

2.异步API都有哪些呢?

常见的异步调用有:定时任务(setTimeout),Ajax以及在此基础之上封装的axios等。

因为异步API的代码执行顺序不同,那么在异步API中,后面的代码需要依赖异步API的结果,那应该如何处理呢?

方式一:嵌套

把后面代码写到异步API的回调函数中,以Ajax请求举例如下:

$.ajax({
  url: 'http://localhost:3000/data',
  success: function(data) {
    console.log(data)
    $.ajax({
      url: 'http://localhost:3000/data1',
      success: function(data) {
        console.log(data)
        $.ajax({
          url: 'http://localhost:3000/data2',
          success: function(data) {
            console.log(data)
          }
        });
      }
    });
  }
});

此时的确可以解决异步的问题,当第一个请求成功之后会执行第二个请求,但是这种方式存在缺点:
1.影响性能,不易维护
2.如果嵌套层次过多,会形成回调地狱

方式二:Promise

Promise的基本用法:实例化Promise对象,构造函数中传递参数,该函数用于处理异步任务;resolve处理成功的情况,reject处理失败的情况,p.then获取处理的结果

var p = new Promise(function(resolve, reject) {
  // 这里用于实现异步任务
  setTimeout(function() {
    var flag = true;
    if (flag) {
      // 正常情况
      resolve("hello");
    } else {
      // 异常情况
      reject("出错了");
    }
  }, 100);
});
p.then(
  function(data) {
    console.log(data);
  },
  function(info) {
    console.log(info);
  }
);

如果使用Promise发送多次Ajax请求,写法如下:

queryData('http://localhost:3000/data')
.then(function(data){
    console.log(data)
    return queryData('http://localhost:3000/data1');
})
.then(function(data){
  console.log(data);
  return queryData('http://localhost:3000/data2');
})
.then(function(data){
  console.log(data)
});

使用Promise的好处:
①可以避免多层异步调用嵌套问题
②简洁的API,更加容易控制异步操作

缺点:写法有些复杂

方式三:async/await

async关键字用于函数上(async函数的返回值是Promise实例对象);
await关键字用于async函数当中(await promise 它可以暂停异步函数的执行,等待promise对象返回结果后再向下执行函数)

下面用setTimeout异步函数说一下async/await的基本用法:

data: {
  test: ''
},
methods: {
  async queryData() {
    var ret = await new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("nihao");
      }, 1000);
    });
    this.test = ret;
    return ret
},
mounted(){
  this.queryData().then(data => {
    console.log(data);            
  })         
}

这样在mounted函数中可以获取到queryData函数返回的ret值。这种方法还有一个变形如下(主要是mounted中发生了改变):

async mounted(){
  // this.queryData().then(data => {
  //   console.log(data);            
  // })
  await this.queryData()
  console.log(this.test);          
}

为什么会有这种变形呢?读者可以尝试一下,变形前在mounted中打印console.log(this.test);是空,而变形后是nihao

使用async/await处理多个异步任务的方法如下:

async queryData() {
  var ret = await new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("nihao");
    }, 1000);
  });
  var res = await new Promise((resolve,reject) => {
    resolve(ret + 'hpp')  
  })
  this.test = res; 
}

上述代码中,在第二个异步任务中也可以使用第一个异步任务的返回结果。

总结

由此,最终推荐使用async/await,应该可以满足读者处理异步函数的需要了。

原创文章 212 获赞 138 访问量 9万+

猜你喜欢

转载自blog.csdn.net/m0_37508531/article/details/105614989