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等方法,我们可以更好地处理异步操作,实现更灵活、高效的代码设计

相关推荐
EndingCoder2 分钟前
React从基础入门到高级实战:React 核心技术 - 表单处理与验证深度指南
前端·javascript·react.js·前端框架
EndingCoder4 分钟前
React从基础入门到高级实战:React 核心技术 - React 与 TypeScript:构建类型安全的应用
前端·安全·react.js·typescript·前端框架
谢尔登5 分钟前
【React】jsx 从声明式语法变成命令式语法
前端·react.js·前端框架
kooboo china.1 小时前
Tailwind css实战,基于Kooboo构建AI对话框页面(二)
前端·css
啃火龙果的兔子2 小时前
判断手机屏幕上的横向滑动(左滑和右滑)
javascript·react.js·智能手机
yuanmenglxb20044 小时前
react基础技术栈
前端·javascript·react.js
coding随想5 小时前
从SPDY到HTTP/2:网络协议的革新与未来
javascript
Magnum Lehar5 小时前
vulkan游戏引擎vulkan部分的fence实现
java·前端·游戏引擎
一枚码农4045 小时前
使用pnpm、vite搭建Phaserjs的开发环境
javascript·游戏·vite·phaserjs
FreeBuf_5 小时前
恶意npm与VS Code包窃取数据及加密货币资产
前端·npm·node.js