Promise学习笔记

news/2024/7/19 14:41:41 标签: js

Promise学习笔记

  • 一、概念
  • 二、对象的使用
    • 1、封装函数创建对象
    • 2、then( )方法
  • 三、JavaScript异步
    • 1、同步
    • 2、异步
      • a、同步回调
      • b、异步回调
      • c、ajax异步
    • 3、ES6新的对象Promise
    • 4、迭代器(Iterator)和生成器(Generator)
    • 5、async和await
  • 四、回调队列和事件循环(event loop)
    • 1、event loop
    • 2、宏队列
    • 3、微队列
    • 4、执行顺序(同步->微任务->宏任务)
    • 5、流行的面试题
  • 五、then方法中返回return

一、概念

Promise对象是JavaScript异步操作解决方案,为异步操作提供统一接口。Promise对象的三种状态:未完成(pending)、已完成(fulfilled)、失败(rejected)

二、对象的使用

1、封装函数创建对象

function getFoo() {
    let p=new Promise((resolve,reject)=>{
        if (/* 异步操作成功 */true) {
            resolve(value);
        }else{
            reject(error);
        }
    });
    return p;
}

2、then( )方法

指定resolve方法和reject方法的回调函数

const prom=getFoo();
prom.then(v=>{
   // success
},e=>{
  // failure
})

三、JavaScript异步

1、同步

function fun1() {
   console.log("函数1");
 }
 function fun2() {
   console.log("函数2");
 }
 fun1();
 fun2();

2、异步

a、同步回调

function fun1(fun) {
    console.log("函数1");
    fun();
}
function fun2() {
  console.log("函数2");
}
fun1(fun2);

b、异步回调

function fun1(fun) {
    setTimeout(function () {
         fun();
       }, 0);
       console.log("函数1");        
}
function fun2() {
  console.log("函数2");
}
fun1(fun2);
for (let i = 0; i <= 10000; i++) {
  console.log("i:", i);
}

在异步回调时,就算fun2()函数放在最上面,而且fun1()函数外面有一个大的for循环,打印结果:

函数1
i:0
......
i:10000
函数2

而且,setTimeout函数的延时为0;到此,我对异步的理解为,当JS文件内所有的同步事件结束后,再回过头来执行所有的异步事件,而异步事件也是按照其所在的异步事件等级(比如异步中包含异步,形成第一级异步、第二级异步…)形成同等级异步的同步事件。(后来我又看到,异步事件又分为宏队列和微队列,详见四)

c、ajax异步

AJAX中根据async的值不同分为同步(async = false)和异步(async = true)
在异步模式下:
****首先:js向服务器发出请求,在等待数据时,ajax后面的同步事件按序依次执行。这样,如果等待数据的时间过长或者等不到数据,都不影响其他事件的执行。
****其次:当数据返回成功时,ajax调用回调函数处理数据。这里有个问题,就是数据返回得很快,js也不是立即执行回调函数,由于是异步事件,需要等同步事件都执行完后再开始执行异步事件。也就是,如果js文件的同步事件执行完需要10分钟(夸张了点),而ajax数据1分钟就返回成功了,但是对不起,ajax的回调函数得10分钟后执行。

$.ajax({
  type: "get",
  url: "./data/productlist.json",
  dataType: "json",
  success: function (data) {
    console.log(data);
  },
});
function fun1(fun) {
  setTimeout(function () {
    fun();
  }, 0);
  console.log(1);
}
function fun2() {
  console.log(2);
}
fun1(fun2);
for (let i = 0; i <= 500; i++) {
  console.log("i:", i);
}
for (let i = 0; i <= 500; i++) {
  console.log("b:", i);
}

再次:在上例中,ajax异步和fun2异步两个回调函数,处于同级别异步事件中,按次序执行。这样就又回到了原问题,当ajax异步回调函数执行时间过长时,将会影响到其他异步事件的执行。有办法,让异步函数的的回调函数,也变成异步,由此,**“回调地狱”**到来了。

$.ajax({
   type: "get",
   url: "./data/productlist.json",
   dataType: "json",
   success: function (data) {
       setTimeout(function () {
           console.log(data);
       }, 0);         
   },
 });

3、ES6新的对象Promise

Promise提供了一种更合理、更强大的异步解决方案,回调函数变成了链式写法,程序的流程可以看得很清楚,而且有一整套的配套方法,可以实现许多强大的功能。

const prom=getFoo();
prom.then(v=>{
   // success
},e=>{
  // failure
})

prom.then(回调函数),而且,prom.then(回调函数)也是一个Promise对象,**“回调地狱”**可以写成prom.then(回调函数1).then(回调函数2).then(回调函数3).then(回调函数4)…
网上一个同学的面试题:https://www.jianshu.com/p/c613c0198430

var promise = new Promise(function(resolve, reject) {
    console.log('Promise instance');
    resolve();
});

promise.then(function() {
   console.log('resolved result');
});
for(var i=0;i<100;i++) {
console.log(i);
}

程序的打印顺序

4、迭代器(Iterator)和生成器(Generator)

ES6新增的异步操作的方法,还没有好好学

5、async和await

在ES7中,async函数处理异步,是生成器的一种语法糖,简化了外部执行器的代码,同时利用await替代yield,async替代生成器的(*)号。
参考:https://zhuanlan.zhihu.com/p/74637286

四、回调队列和事件循环(event loop)

1、event loop

event loop它最主要是分三部分:主线程、宏队列(macrotask)、微队列(microtask)。
js的任务队列分为同步任务和异步任务,所有的同步任务都是在主线程里执行的,异步任务可能会在macrotask或者microtask里面。

2、宏队列

setTimeout、setInterval、setImmediate、I/O、UI rendering
DOM 的回调、Ajax 的回调

3、微队列

promise.then、process.nextTick
在这里插入图片描述

4、执行顺序(同步->微任务->宏任务)

• JS 引擎先去执行所有的同步代码
• 然后执行队列中的任务
• 在一个一个宏任务执行前,会先检查微任务的执行,必须等所有微任务执行完才会一个一个去执行宏任务

5、流行的面试题

async function asycn1() {
  console.log('async1 start');
  await async2();
  console.log('async1 end');
}

async function async2() {
  console.log('async2');
}

console.log('script start');

setTimeout(() => {
  console.log('setTimeout ');
}, 0);

asycn1();

new Promise((resolve) => {
  console.log('promise1');
  resolve();
}).then(() => {
  console.log('promise2');
});

console.log('script end');

参考:https://blog.csdn.net/weixin_41884153/article/details/90737448
https://www.cnblogs.com/BAHG/p/12921321.html
https://blog.csdn.net/weixin_44138611/article/details/112464382

五、then方法中返回return

应用场景:在页面加载时,异步函数A获得对象数组arr,再调用一个函数B对数组arr进行过滤,而这个函数B里有用另一个异步函数C的结果再进行一次过滤,过滤出来的结果返回给A继续使用处理。
一个问题:如果函数B是个普通函数,那么异步函数C里的结果resultArr我没有办法return resultArr出来,需要将函数B做成Promiss对象

// 函数A
getObjectData('objDetail').then(res => {
    payMonth(res,selectMonth.split('-')[1],selectMonth.split('-')[0]).then(res=>{
        console.log(res);
    })
})
// 函数B
// 月支出总计
export function payMonth(arr,month,year){
    let dateArr=new Promise((resolve,reject)=>{
    let monthArr=[]
    let payClassMon=''
    let payArr = arr.filter(item =>
        item.incomePay == 0 && item.date.split(' ')[0].split('-')[0] == year && item.date.split(' ')[0].split('-')[1]==month
    )
    if (payArr) {
        // 月总支出
        let pay = payArr.reduce((total, value, index, array) => {
            return total + parseFloat(value.money);
        }, 0) 
        monthArr.push({'payMonthCount':pay})
        // 类别 函数C
        getObjectData('classIncome').then(res=>{
            if (res) {
                for(let ele of res){
                    let payClassArr = payArr.filter(item =>
                        item.aclass==ele
                    )
                    if (payClassArr.length>0) {
                        payClassMon = payClassArr.reduce((total, value, index, array) => {
                            return total + parseFloat(value.money);
                        }, 0)
                        monthArr.push({'aclass':ele,'classPay':payClassMon})
                    }
                }  
            }
            resolve(monthArr);     
        })
    }
})
return dateArr;
}

http://www.niftyadmin.cn/n/1409639.html

相关文章

使用Excel消费C4C的OData service

2019独角兽企业重金招聘Python工程师标准>>> 步骤比较简单, 打开Excel的标签Data->From Other Sources->From OData Data Feed: 输入如下url: https://<your tenant>.c4c.saphybriscloud.cn/sap/byd/odata/v1/c4codata/ 选择AccountCollection: 这个例子…

html一个页面中切换多个页面_一个页面多个重复链接,对SEO有作用吗?

在以往的SEO工作中&#xff0c;我们经常会发现一个问题&#xff0c;很多SEO人员&#xff0c;为了提高目标页面的关键词排名&#xff0c;经常是在同一页面&#xff0c;发布大量重复指向目标页面的链接。 那么&#xff0c;一个页面&#xff0c;多个重复链接&#xff0c;对SEO有作…

event loop学习笔记

event loop学习笔记1、同步任务和DOM渲染2、加入ajax3、加入setTimeout4、加入Promise5、宏任务中加入微任务6、微任务中的宏任务、宏任务中的宏任务7、微任务中的微任务8、axios1、同步任务和DOM渲染 console.log("****event-start****"); $("div").appe…

List集合就这么简单【源码剖析】

前言 声明&#xff0c;本文用得是jdk1.8 前一篇已经讲了Collection的总览&#xff1a;Collection总览&#xff0c;介绍了一些基础知识。 现在这篇主要讲List集合的三个子类&#xff1a; ArrayList 底层数据结构是数组。线程不安全LinkedList 底层数据结构是链表。线程不安全Vec…

软件工程 第4版张海藩 pdf_2019年第4期软件工程造价师培训课程圆满结束

2019年2月20至22日&#xff0c;由北京软件造价评估技术创新联盟举办的2019年第4期(总第208期)软件工程造价师培训课程在北京圆满结束。来自系统工程所、江苏国创新云、东软望海科技等公司的近20名学员参加培训。培训课上&#xff0c;培训老师系统讲解了国家标准和行业标准中规定…

vue挂载前后与DOM渲染-学习笔记

vue挂载前后与DOM渲染mounted二级目录三级目录mounted 二级目录 三级目录

400 bad request什么意思_从婚姻中学到最重要的5条经验是什么?

1. Housework is not a womans responsibility alone做家务不仅仅是女人的职责Home is the home of two people, and housework should be shared by two people. Its not a womans responsibility to do housework alone. Men also have a share.家是两个人的家&#xff0c;家…

【视频音频】雷霄骅开源视音频项目汇总

【视频音频】雷霄骅开源视音频项目汇总