Promise:解决JavaScript异步编程难题(一)

引言

在现代的Web开发中,JavaScript异步编程一直是一个备受关注的话题。长期以来,开发者们一直在寻求一种简洁而强大的解决方案,以有效地处理异步操作,避免回调地狱(callback hell)并提高代码的可读性和可维护性。正是在这样的背景下,Promise作为一种解决JavaScript异步编程难题的新思路应运而生。这篇文章,我将教会大家如何使用promise。

异步

异步(asynchronous)是指在程序执行过程中,不需要等待某个操作的完成,而可以继续执行后续的操作。相比于同步(synchronous)操作,异步操作可以提高程序的效率和响应性。

在编程中,异步操作通常用于处理那些耗时较长的任务,如网络请求、文件读写、数据库查询等。在传统的同步编程模型中,程序会在执行这些任务时被阻塞,直到任务完成后才能继续执行后续的代码。而在异步编程模型中,程序可以发起这些任务,然后立即继续执行后续的代码,而不需要等待任务完成。

我们来模拟一下异步:

js 复制代码
function a() {
    setTimeout (() => {
        console.log('阿珍')
    },1000);

}

function b() {
    setTimeout(()=>{
        console.log('阿强')
    },0)
}
a()
b()

a()中我们让阿珍等待1s输出,此时我们的V8先执行b(),等到1s结束后再执行了a(),所以运行结果为=> 阿强 阿珍,这就是异步,先执行a()发现方法需要等待就立刻执行接下来的程序,大大提高了js的执行效率。

异步存在的问题

当我们的b()方法需要依赖a()的结果进行运行,那么掘友们聪明的脑袋瓜子应该能发现,当a()方法还在等待,而需要依赖a()方法结果的b()却提前运行了,这是不符合逻辑的,接下来我们来模拟一下异步的问题

js 复制代码
function a(){
    setTimeout(()=>{
         consol.log('我去相亲了')
    },2000)
   
}
function b(){
    setTimeout(()=>{
         consol.log('我要结婚了')
    },1000)
   
}
a()
b()

显而易见,咱们得先相亲再结婚,并且相亲花费的时间要比结婚长,但是当我们运行程序时,输出的却是先结婚再相亲,这就是异步问题所在

回调地狱

以前的程序是如何解决这个问题的呢?

js 复制代码
function a() {
    setTimeout ((cb) => {
        consol.log('我去相亲了')
        cb()
    },2000);

}

function b() {
    setTimeout(()=>{
        consol.log('我要结婚了')
    },1000)
}
a(b)

以前,程序员们将b()方法放入a()中执行,于是便实现了a()先执行b()再执行。但是,我们的一个项目拥有非常多的方法,很多方法都要依赖别的方法结果来执行,所以程序员们得不停地在方法里回调其他方法,就像将所有的方法串成一根绳子,只要有一个地方断了,所有的程序都会出现错误,这就是回调地狱,使得代码的维护极其困难。

Promise

关于Promise的使用,我们先来看以下代码:

js 复制代码
function xq(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log('我相亲了');
            resolve('相亲成功')//可以抛出一个值在.then()接收
        },2000)
    })
}
function marry(){
    return new Promise((resolve, reject) => {
        setTimeout(()=>{
            console.log('我结婚了');
            resolve()
        },1000)
    })
    
}
function baby(){
    setTimeout(()=>{
        console.log('小龙女出生');
    },500)
}
xq().then((res)=>{
    console.log(res);
    return marry()//如果不使用return marry(),那么后面的.then()会调用默认的promise 从而baby()
                  //与marry()一起执行,形成异步
})
.then((res2)=>{    
    baby()
})
  1. xq 函数返回一个Promise对象,表示"我相亲了"这个任务。在Promise中,我们使用setTimeout模拟了一个耗时2秒的相亲过程。当相亲成功后,Promise会调用resolve方法,并传递相亲成功的消息。
  2. marry 函数也返回一个Promise对象,表示"我结婚了"这个任务。在Promise中,我们同样使用setTimeout模拟了一个耗时1秒的结婚过程。当结婚成功后,Promise会调用resolve方法。
  3. baby 函数是一个简单的定时任务,用于模拟"小龙女出生"的过程。
  4. 在主程序中,我们首先调用 xq() 函数,然后使用 .then() 方法来处理相亲成功后的结果。在第一个 .then() 中,我们输出了相亲成功的消息,并调用了 marry() 函数。由于我们在 .then() 中使用了 return marry(),所以后续的 .then() 会等待 marry() 的完成。
  5. 在第二个 .then() 中,我们输出了结婚成功的消息,并调用了 baby() 函数。由于 baby() 函数没有被包裹在Promise中,它会立即执行,而不会等待前面的异步操作完成。

细节

1.resolve 和 reject

在Promise中,resolve和reject是两个函数,用于表示Promise对象的状态。当一个异步操作成功完成时,我们会调用resolve函数来将Promise状态从pending(进行中)变为fulfilled(已成功);当异步操作发生错误或失败时,我们会调用reject函数来将Promise状态从pending变为rejected(已失败)。注意,如果在方法中调用了reject()方法,在全局调用方法时不捕获异常将会报错。

2.return marry()

细心的掘友们会发现,为什么我们在.then()中要return marry()呢?原来是因为如果不使用return marry(),那么后面的.then()会调用默认的promise 从而baby()方法会和marry()方法形成异步。

Promise.all() 和 Promise.race()

关于这两个方法我们先看以下代码:

js 复制代码
function a(){
    return new Promise((resolve,reject) =>{
        setTimeout(()=>{
            console.log('a');
            resolve('yes')//顺利执行 reject() 执行出错
        },2000)
    }) 
}
function b(){
    return new Promise((resolve,reject) =>{
        setTimeout(()=>{
            console.log('b');
            resolve()
        },1500)
    }) 
}
function c(){
    setTimeout(()=>{
        console.log('c');
    })
}
// a()
// b()
// c()
//Promise.all([a(),b()]).then(c)//c 将c函数体传进去 加括号是将c()运行结果传进去
//a(),b() 要有返回promise的能力
//all必须要接收到的所b有的promise状态都为resolve,then才会调用
Promise.race([a(),b()])
.then(c)
.catch((err)=>{
    console.log(err);
})
//a,b谁快.then就接在谁后面执行
  • Promise.all

c 将c函数体传进去 加括号是将c()运行结果传进去,a(),b() 要有返回promise的能力,all必须要接收到的所有的promise状态都为resolve,then才会调用

  • Promise.race

Promise.race会等待a和b中任意一个任务完成,然后立即执行后续的操作。.catch()方法是用来捕获方法中的异常,使其不报错并且更好地找到错误的地方

结尾

希望以上解析能够帮助您理解Promise的基本概念和使用方法。通过合理运用resolve和reject函数、Promise链式调用以及Promise.race等方法,我们可以更好地处理异步操作,实现更灵活、高效的代码设计

相关推荐
WeiXiao_Hyy4 小时前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端
吃杠碰小鸡5 小时前
高中数学-数列-导数证明
前端·数学·算法
kingwebo'sZone5 小时前
C#使用Aspose.Words把 word转成图片
前端·c#·word
xjt_09015 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农5 小时前
Vue 2.3
前端·javascript·vue.js
夜郎king6 小时前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
辰风沐阳6 小时前
JavaScript 的宏任务和微任务
javascript
夏幻灵7 小时前
HTML5里最常用的十大标签
前端·html·html5
冰暮流星7 小时前
javascript之二重循环练习
开发语言·javascript·数据库
Mr Xu_7 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js