Promise

相关学习网站。本期简单介绍Promise,

如果大家喜欢下次将会和大家一起学习Promise源码分析

目录

异步编程

Promise

异步编程实现

属性

PromiseState

PromiseResult

基本流程

Promise ajax请求

Promise使用

构造函数

then

catch

resolve

​编辑

reject

all

race

链式调用

中断链条

异常穿透

Node.js相关核心模块

fs

util

util.promisify


异步编程

在js执行过程中可以随时进行其他任务而不必等待某个任务完成

需要异步编程的类型:

  • 定时器

  • fs文件操作

  • ajax

  • 数据库操作

解决方法:

  • 回调函数

    • 定时器

    • fs文件操作

    • ajax

    • 数据库操作

  • promise

    优点:

    1. 指定回调函数方式更灵活

    2. 支持链式调用,可以解决回调地狱问题

      回调地狱问题:回调函数里嵌套多层异步编程

Promise

Promise是JavaScript中用于处理异步操作的一种机制

异步编程实现

  • 定时器

    fun(){       
        //创建promise对象
        const p=new Promise((resolve,reject)=>{
            //定时器模拟把响应发送到服务器再返回时间
            setTimeout(
                ()=>{
                    //生成1~100间随机数
                    let a=Math.ceil(Math.random()*100)
                    if(a<30){resolve(a)}  //对象成功时调resolve函数,并且把对象状态设置为 成功
                    else{reject(a)}       //对象成功时调reject函数,并且把对象状态设置为 失败
                },
                1000)//延时1秒
        })
    ​
        //调用then( 对象成功时回调函数 , 对象失败时回调函数 )
        p.then(
            (value)=>{alert("真tm牛x,这都叫你给中了!奖励奔驰大G一辆!!!"+a)},
            (reason)=>{alert("没中,哈哈..."+a)})
    }
    • 创建promise对象

      new Promise( (resolve,reject)=>{...} )

      • resolve(解决):对象成功时调resolve函数,并且把对象状态设置为 成功

      • reject(拒绝):对象不成功时调reject函数,并且把对象状态设置为 失败

    • then方法,设置成功/失败函数

      p.then( (value)=>{成功}, (reason)=>{失败})

  • fs文件操作

    //Node.js中引入核心模块fs,用于文件操作
    const fs=require('fs')
    ​
    ​
    //创建promise对象
    let p=new Promise((resolve,reject)=>{
        //fs.readFile('目标文件位置',(err,data)=>{...})
        fs.readFile('../resource/txt.txt',
        (err,data)=>{
            //如果有错,调reject(err)
            if(err){reject(err)}
            //成功调resolve(data)
            resolve(data)
        })
    })
    ​
    //调用then()
    p.then(
        (value)=>{console.log(value.toString())},
        (reason)=>{console.log(reason)}
    )

    执行方法是在集成终端打开文件夹,输入 node fs_demo.js

    fsNode.js中核心模块.用于文件操作

  • ajax

    $("input").click(()=>{
                //创建promise对象
                const p=new Promise((resolve,reject)=>{
                    //$.get( 发送请求的url ,成功后的回调函数 )
                    $.get(
                        'https://api.apiopen.top/getJoke',
                        (response)=>{resolve(response)}
                    )
                    .fail((status)=>{
                        reject(status)
                    });
                })
                //调用then()
                p.then(
                    (value)=>{console.log(value)},
                    (reason)=>{console.log(reason)}
                )
            })

属性

PromiseState

是promise内置的一种属性,表示promise状态.

PromiseState有以下三种取值:

  1. 待定(pending):初始状态,既没有被兑现,也没有被拒绝。

  2. 已兑现(resolved/fulfilled):意味着操作成功完成。

  3. 已拒绝(rejected):意味着操作失败。

如果一个 Promise 已经被兑现或拒绝,即不再处于待定状态,那么则称之为已敲定(settled)

  • 状态改变

    1. 待定 --> 已兑现

    2. 待定 --> 已拒绝

    • 只能有这两种情况

    • promise状态只能改变一次

  • 改变Promise状态方法

    • resolve('PromiseResul结果值') pending-->fulfilled/resolved

    • reject('PromiseResul结果值') pending-->rejected

    • throw 'PromiseResul结果值' pending-->rejected

PromiseResult

是promise内置属性,保存异步任务对象promise成功/失败后返回结果

可以通过resolve()或reject()对PromiseResult赋值

基本流程

流程图展示了 Promise 状态在 pending、fulfilled 和 rejected 之间如何通过 then() 和 catch() 处理程序进行转换。

一个待定的 Promise 可以变成已兑现或已拒绝的状态。

如果 Promise 已经兑现,则会执行“on fulfillment”处理程序(即 then() 方法的第一个参数 ),并继续执行进一步的异步操作。

如果 Promise 被拒绝,则会执行错误处理程序,可以将其作为then() 方法的第二个参数catch() 方法的唯一参数来传递。

Promise ajax请求

  • 自己封装promis sendAJAX(url): 向url发送get ajax请求

    • 在项目整体包下初始化npm项目: 项目名>npm init --yes

    • 在项目的code下安装Express框架: 项目名/code>npm i express

      启动一个 Node.js 服务器: 项目名/code>node server.js

    server.js内容参考ajax笔记

//自己封装: promise sendAJAX(url):向url发送get ajax请求
function sendAJAX(url){
    return new Promise((resolve,reject)=>{
        $.get( url, (Response)=>{resolve(Response)})
            .fail(()=>{reject(state)})
    })
}
​
//Test
sendAJAX('http://127.0.0.1:8000/jquery_server').then(
    (value)=>{console.log(value)},
    (reason)=>{console.warn(reason)}
)

Promise使用

构造函数

new Promise(executor)

  • executor函数: 执行器,会在promise内部同步调用(立即执行),异步操作在执行器中执行

    (resolve,reject)=>{...}

    • resolve函数: 内部定义的,成功时调用(value)=>{...}

    • reject函数: 内部定义的,失败时调用(reason)=>{...}

then

Promise Promise.prototype.then(onResolved,onRejected)

Promise.prototype可以自定义或修改内置的 Promise 方法的行为

then为Promise指定成功/失败回调,

返回一受回调函数影响的新Promise (可链式调用 )

let result=p.then((value)=>{回调函数})
  • 回调函数抛出异常: ```throw "异常"

    返回Promise 状态:失败, 结果:"异常"

  • 回调函数返回结果为非Promise对象: ```return 666

    返回Promise 状态:成功, 结果:666

  • 回调函数返回结果为Promise对象: ...

    返回Promise 状态和结果都和回调函数return的Promise对象一样

  • 回调函数无返回值

    返回的Promise 状态:成功, 结果:undefined

若指定多个回调,则当Promise对象状态改变时都会执行

  • onResolved回调: 成功时回调 (value)=>{...} ,返回新Promise对象

  • onRejected回调: 失败时调用(reason)=>{...}

catch

Promise.prototype.catch(onRejected)

是实例的方法

  • onRejected回调: 失败时调用(reason)=>{...}

resolve

Promise Promise.resolve(value)

不是实例的方法,是Promise对象的方法

不用构造函数,Promise.resolve(...)也可以创建一个Promise对象

  • value:传入PromiseResult值, 可以是Promise类型也可以是非Promise类型

//当传入参数为非Promise类型对象时,返回PromiseState为成功的Promise对象
let p1=Promise.resolve(666)
console.log(p1)
​
​
//当传入参数为Promise类型对象时,返回PromiseState取决于参数Promise
let p2=Promise.resolve(new Promise((resolve,reject)=>{
    /*当内部Promise回调成功,p2PromiseState也成功
    resolve('ok')*/
    
    //当内部Promise回调失败,p2PromiseState也失败
    reject('error') 
}))
p2.catch((reason)=>{
    console.log(reason)
})

reject

Promise Promise.reject(reason)

Promise对象的方法

返回失败的Promise对象

  • reason:传入PromiseResult值

//Promise Promise.reject(传入PromiseResult值)
let p=Promise.reject(666)
//失败后处理
p.catch((reason)=>{
    console.log(reason)
})
​
console.log(p)

all

Promise Promise.all(Promise[])

传入Promise数组,返回一个新Promise对象,其PromiseState取决于Promise数组

  • 当Promise数组PromiseState全成功时,

    新Promise对象PromiseState成功

    新Promise对象PromiseResult为Promise数组的PromiseResult组成的数组

  • 否则,新Promise对象PromiseState失败

    新Promise对象PromiseResult为 Promise数组 中第一个失败Promise的PromiseResult

Promise对象方法

//当Promise数组全成功
let p1=Promise.resolve('111')
let p2=Promise.resolve('222')
let p3=Promise.resolve('333')
​
let p=Promise.all([p1,p2,p3])
console.log(p)

//当Promise数组中存在失败的
let p1=Promise.resolve('111')
//p2,p3都失败, 但最终p的PromiseResult为第一个失败的PromiseResult
let p2=Promise.reject('222')
let p3=Promise.reject('333')
​
let p=Promise.all([p1,p2,p3])
console.log(p)

race

Promise Promise.race(Promise[])

传入Promise数组,返回一个新Promise对象,

新对象=第一个改变状态的Promise

Promise对象的方法

let p1=new Promise((resolve,reject)=>{
            setTimeout(()=>{resolve('111')},1000) //p1等1秒后状态改为成功
        })
        let p2=Promise.resolve('222')   //p2是第一个改变状态的
        let p3=Promise.reject('333')
​
        let p=Promise.race([p1,p2,p3])  //返回结果=p2
        console.log(p)

链式调用

链式调用:回调方法then返回Promise对象又可以对其使用.then(...)

//p 状态:成功, 结果:'ok'
let p=new Promise((resolve,reject)=>{
    setTimeout(()=>{resolve('ok')},1000) //p等1秒后状态改为成功
})
​
//返回Promise 状态:成功, 结果:undefined(因为回调函数没return)
p.then((value)=>{console.log(value)})   //value(结果):undefined
.then((value)=>{console.log(value)})

为了更快的执行,最好将所有同步操作都放在一个处理程序中,否则如果将它们拆分为多个处理程序,执行所有处理程序将需要几个时钟周期。

中断链条

链中每个已兑现的 Promise 的返回值会传递给下一个 .then(),

而已拒绝的 Promise 会把失败原因传递给链中下一个拒绝处理函数。

当且仅当Promise状态为 待定(pending)时才会中断链条

因为待定的Promise状态未改变,不能调用.then()

let p=new Promise((resolve,reject)=>{
    setTimeout(()=>{resolve('ok')},1000) //p等1秒后状态改为成功
})
​
p.then((value)=>{console.log('111')})
//返回pending状态的Promise无法调用.then()
    .then((value)=>{console.log('222');return new Promise(()=>{})})
    .then((value)=>{console.log('333')})
    .catch((reason)=>{console.warn(reason)})

异常穿透

穿透处理:当有多个then链式调用时,在最后加上.catch((reason)=>{异常处理})

无论是哪一环失败了,都会执行'异常处理'

let p=new Promise((resolve,reject)=>{
    setTimeout(()=>{resolve('ok')},1000) //p等1秒后状态改为成功
})
​
p.then((value)=>{console.log('111')})
.then((value)=>{console.log('222');throw '出错了'})
.then((value)=>{console.log('333')})
.catch((reason)=>{console.warn(reason)})

Node.js相关核心模块

fs

用于文件操作,如读取、写入、删除、重命名文件等

使用fs模块需要先引入该模块 ( const fs=require('fs') )

然后通过调用其提供的API函数来完成相关操作

  • fs.readFile() 读取文件内容

  • fs.writeFile() 写入文件内容

  • fs.unlink() 删除文件

  • fs.rename() 重命名文件

util

在 Node.js 中有一个内置的 "util" 模块

用于提供一系列实用函数,如格式化字符串、处理对象继承等

util.promisify

util.promisify (js.readFile)

回调-->promise

用于将基于回调的异步函数转换为返回 Promise 的函数

fs.readFile(path,(err,data)=>{...}) --> util.promisify(fs.readFile)

  • 自己封装函数:

    给一个目标文件地址返回一个promise对象

//封装一个函数:promise My_ReadFile('目标文件地址')
​
function My_ReadFile(path){
 return new Promise((resolve,reject)=>{
     //引入fs.读文件
     require('fs').readFile(path,(err,data)=>{
         //失败
         if(err){reject(err)}
         //成功
         resolve(data)
     })
 })
}
​
//Test
My_ReadFile('./resource/txt.txt')
.then(
   (value)=>{console.log(value.toString())},
   (reason)=>{console.warn(reason)}
)
  • util.promisify

//util内置函数promisify(js.readFile)
//引入util
const util=require('util')
​
let ReadFile=util.promisify(require('fs').readFile)
​
//Test
ReadFile('./resource/txt.txt').then(
    (value)=>{console.log(value.toString())},
    (reason)=>{console.warn(reason)}
)

将fs.readFile()函数转换为返回Promise的形式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值