Javascript的异步函数和Promise对象你了解吗

 更新时间:2022年03月11日 15:21:02   作者:小绵杨Yancy  
这篇文章主要为大家详细介绍了Javascript异步函数和Promise对象,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

1、JS中的异步

1.1 同步

一般情况下,js的代码都是自上而下顺序运行的。例如:

let res = '';
res = '获取到的结果!';
console.log(res);

结果:

在这里插入图片描述

很容易理解,我给res赋了新值,然后输出res。这就是js的同步执行,这里的同步,并不是一起执行的意思,而是在一个线程里顺序执行的意思。因为JavaScript是单线程,所以所有程序都应该在一个线程里运行。

1.2 异步

但是有的时候,我们获取res的值是需要一点时间的,例如使用ajax向服务器发起请求,服务器响应以后返回结果,我们再将结果赋值给res。

这里使用setTimeout函数模拟数据请求,setTimeout也是一个异步函数。

let res = '';
setTimeout(()=>{
    res = '获取到的结果!';
    console.log('获取到结果了!',res);
},3000);
console.log('res',res);

在这里插入图片描述

可以看到,没有立刻获取到结果,而是3s后才获取到结果。

为什么会这样呢?
由于获取res它是一个异步操作,所以它会被分为两部分来执行,先调用setTimeout方法,然后把要执行的函数放到一个队列中。代码继续往下执行,当把所有的代码都执行完后,放到队列中的函数才会被执行。因为js的单线程机制,不允许它花费时间去等待异步函数的结果。

1.3 回调函数解决异步问题

既然异步函数的结果会再最后获取,那么我们就可以给异步函数中加一个回调函数,来处理获取到的数据。

let res = '';
setTimeout(()=>{
    res = '获取到的结果!';
    callback();
},3000);
function callback(){
    console.log('获取到结果了!',res);
    console.log('处理结果!');
}
console.log('res', res);

在这里插入图片描述

现在console.log('res', res);仍然没有获取到res,但是我们已经不需要它了,我们获取res的就是为了处理它,而使用callback函数就可以达到目的了!

1.4 回调地狱

1.3了解了可以通过调用函数解决无法获取结果的问题,但是它仍然是存在缺点的,如果只获取一次结果,那还好。但是如果我们在获取结果之后,还需要利用获取的结果再进行异步操作,那么又需要嵌套一层,又需要一次异步操作,再嵌套一层……

setTimeout(function(){
    console.log("first");
    setTimeout(function(){
        console.log("second");
        setTimeout(function(){
            console.log("third");
            setTimeout(function(){
                console.log("fourth");
            },2000);
        },2000);
    },2000);
},2000);

虽然上述代码会按照我们预期的方向运行,但是多层的嵌套让代码阅读和维护起来十分的困难。

2、Promise对象

2.1 Promise的基本使用

为了解决异步中的回调地狱问题,ES6引入了Promise对象,使得我们可以十分优雅地进行异步操作。
从语法上来说,Promise是一个对象,从它可以获取异步操作的消息。

let timeout = function(time){
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            resolve();
        },time);
    });
}
console.log("开始运行!");
timeout(2000).then(function(){
    console.log("first");
    return timeout(2000);
}).then(function(){
    console.log("second");
    return timeout(2000);
}).then(function(){
    console.log("third");
    return timeout(2000);
}).then(function(){
    console.log("fourth");
    return timeout(2000);
});

在这里插入图片描述

这样就解决了上述的回调地狱的问题。并且then也很容易理解,就是上一个异步函数执行完成后,接着要进行的操作。

同时Promise对象也可以通过resolve和reject传递参数:

let res = null;
let timeout = function(time){
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            res = false;
            if(res){
                resolve('res为true');
            }else{
                reject('res为false');
            }
        },time);
    });
}
timeout().then((res)=>{
    console.log(res);
}).catch((error)=>{
    console.log(error);
})

这样就可以根据res的值来确定结果了。resolve()对应then的结果,而reject()对应catch的结果。这在axios的请求操作中是十分常见的。

2.2 async 和 await

mdn描述如下:

async函数是使用async关键字声明的函数。 async函数是AsyncFunction构造函数的实例, 并且其中允许使用await关键字。async和await关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise。

async和await的关系:

async函数可能包含0个或者多个await表达式。await表达式会暂停整个async函数的执行进程并出让其控制权,只有当其等待的基于promise的异步操作被兑现或被拒绝之后才会恢复进程。promise的解决值会被当作该await表达式的返回值。使用async / await关键字就可以在异步代码中使用普通的try / catch代码块。

function getProcessedData(url) {
  return downloadData(url) // 返回一个 promise 对象
    .catch(e => {
      return downloadFallbackData(url)  // 返回一个 promise 对象
    })
    .then(v => {
      return processDataInWorker(v); // 返回一个 promise 对象
    });
}

使用async和await重写上述函数。

async function getProcessedData(url) {
  let v;
  try {
    v = await downloadData(url);
  } catch (e) {
    v = await downloadFallbackData(url);
  }
  return processDataInWorker(v);
}

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容! 

相关文章

  • JavaScript打印iframe内容示例代码

    JavaScript打印iframe内容示例代码

    打印iframe内容的方法有很多,下面为大家简单介绍下使用JavaScript实现打印,有需求的朋友可以参考下
    2013-08-08
  • 基于jsbarcode 生成条形码并将生成的条码保存至本地+源码

    基于jsbarcode 生成条形码并将生成的条码保存至本地+源码

    这篇文章主要介绍了基于jsbarcode 生成条形码并将生成的条码保存至本地,本文给大家提供最新源代码,代码简单易懂,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧
    2020-04-04
  • JavaScript面向对象精要(上部)

    JavaScript面向对象精要(上部)

    这篇文章主要介绍了JavaScript面向对象精要,需要的朋友可以参考下
    2017-09-09
  • 用VsCode编辑TypeScript的实现方法

    用VsCode编辑TypeScript的实现方法

    这篇文章主要介绍了用VsCode编辑TypeScript的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • 老生常谈js中的MVC

    老生常谈js中的MVC

    下面小编就为大家带来一篇老生常谈js中的MVC。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • JavaScript异步编程常见面试题汇总

    JavaScript异步编程常见面试题汇总

    本文将带大家学习异步编程这一块内容,鉴于异步编程是js中至关重要的内容,所以我们将学习异步编程涉及到的重点和难点,同时这一块内容也是面试常考范围,希望对大家有所帮助
    2023-02-02
  • JavaScript之WebSocket技术详解

    JavaScript之WebSocket技术详解

    这篇文章主要为大家详细介绍了JavaScript之WebSocket技术,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • JavaScript实现将数组数据添加到Select下拉框的方法

    JavaScript实现将数组数据添加到Select下拉框的方法

    这篇文章主要介绍了JavaScript实现将数组数据添加到Select下拉框的方法,涉及javascript数组操作及页面元素动态赋值的相关技巧,需要的朋友可以参考下
    2015-08-08
  • JS小数转换为整数的方法分析

    JS小数转换为整数的方法分析

    这篇文章主要介绍了JS小数转换为整数的方法,结合实例形式分析了数值转换的常用方法与使用技巧,需要的朋友可以参考下
    2017-01-01
  • 原生JS实现平滑回到顶部组件

    原生JS实现平滑回到顶部组件

    返回顶部组件是一种极其常见的网页功能,需求简单:页面滚动一定距离后,显示返回顶部的按钮,点击该按钮可以将滚动条滚回至页面开始的位置,接下来通过本文给大家介绍原生JS实现平滑回到顶部组件,需要的朋友参考下吧
    2016-03-03

最新评论