精华内容
下载资源
问答
  • Problem Description Given a string S[0,...n-1],and the length of each palindrome substring in S is less than 20. Define special string of a palindrome string STR[0,...,n-1] is STR[floor(n/2),...,n...
  • 很多人都知道死锁是怎么一回事儿:线程A和线程B相互等待对方持有的锁导致程序无限死循环下去。当然也仅限于此了,问一下怎么写一个死锁的程序就不知道了,这种情况说白了就是不懂什么是死锁,懂一个理论就完事儿了,...
    很多人都知道死锁是怎么一回事儿:线程A和线程B相互等待对方持有的锁导致程序无限死循环下去。当然也仅限于此了,问一下怎么写一个死锁的程序就不知道了,这种情况说白了就是不懂什么是死锁,懂一个理论就完事儿了,实践中碰到死锁的问题基本上是看不出来的。
    真正理解什么是死锁,这个问题其实不难,几个步骤:
    (1)两个线程里面分别持有两个Object对象:lock1和lock2。这两个lock作为同步代码块的锁;
    (2)线程1的run()方法中同步代码块先获取lock1的对象锁,Thread.sleep(xxx),时间不需要太多,50毫秒差不多了,然后接着获取lock2的对象锁。这么做主要是为了防止线程1启动一下子就连续获得了lock1和lock2两个对象的对象锁
    (3)线程2的run)(方法中同步代码块先获取lock2的对象锁,接着获取lock1的对象锁,当然这时lock1的对象锁已经被线程1锁持有,线程2肯定是要等待线程1释放lock1的对象锁的
    这样,线程1″睡觉”睡完,线程2已经获取了lock2的对象锁了,线程1此时尝试获取lock2的对象锁,便被阻塞,此时一个死锁就形成了。代码就不写了,占的篇幅有点多。
    展开全文
  • 已完成的文章本系列文章将在2021年春节前完成,欢迎关注,点赞,评论 --- 梦想橡皮擦五、Python 循环的本质就是一段代码懒得重复写程序中的循环概念非常容易理解,一段相似的代码不想重复去写,然后让程序去完成这个...

    为啥要滚雪球学 Python,目的就是当你学会编程一些思想之后,可以让知识的雪球自行滚动起来。

    已完成的文章

    本系列文章将在2021年春节前完成,欢迎关注,点赞,评论 --- 梦想橡皮擦

    五、Python 循环的本质就是一段代码懒得重复写

    程序中的循环概念非常容易理解,一段相似的代码不想重复去写,然后让程序去完成这个操作就是循环。例如从 1 加到 100,如果你依次去加会发现,代码又臭又长,最好的写法当然是让程序通过循环依次去累加。

    5.1 for 循环

    for 循环可以将对象中元素进行遍历(也叫迭代)操作,每次遍历都可以对元素进行相应的处理,截止到本篇博客,可遍历(迭代)对象目前为列表类型。

    for 循环的语法格式如下:

    for item in my_list(可迭代对象):

    for 代码块

    上述代码中的 item 就是每次循环得到的对象,即可迭代对象里面的每个值。

    这里最重要的一个概念是可迭代对象(iterable object),英文你也需要记住,后面经常用到。

    可迭代对象包含的类型非常多,例如有列表、元组、字典与集合,除了列表以外其它的内容将在后面进行学习。

    5.1.1 for 循环基本使用

    学习列表之后,对于 for 循环你需要建立一个基本的概念就是 for 循环可以依次获取到列表中的每一项,注意是依次获取。

    编写代码的时候与 if 语句一样要注意缩进。

    接下来通过 for 循环打印列表中每一项。

    my_list = ["apple","orange","banana","pear"]

    for item in my_list:

    print(item)

    for 循环语句中只要缩进一致,可以由多行代码构成,例如:

    my_list = ["apple","orange","banana","pear"]

    for item in my_list:

    print("输出一个水果")

    print(item)

    5.1.2 for 循环嵌套 if 判断语句

    for 循环里面可以是多段代码,那这样其实也是可以嵌套 if 语句的,具体写法可以参考:

    my_list = [1,2,3,4,5,6,7]

    for item in my_list:

    if item >3:

    print("该元素比3大")

    print("该元素是:",item)

    上述代码可以判断当列表中的元素大于 3 的时候,输出 if 语句中的内容,你可以尝试补全 else 语句。

    5.2 range 函数

    在 Python 中可以通过 range 函数生成一个等差序列,这个等差序列就是一个可迭代对象,如果使用 type 函数查看对象类型会发现 range 函数生成的对象类型是 range,具体代码如下:

    my_range = range(4)

    print(my_range)

    print(type(my_range))

    输出结果为:

    range(0, 4)

    可以看到 range 函数生成的是一个 range 对象,上文中用到了 range 函数,语法格式为 range(4),通用的语法格式如下:

    range(start,stop,step)

    其中只有 stop 是必填项,step 默认值是 1,如果省略 start 默认表示从 0 到 stop-1。具体运行下述代码即可清楚。

    my_range1 = range(4)

    for i in my_range1:

    print(i)

    print("#"*10)

    my_range2 = range(1,4)

    for i in my_range2:

    print(i)

    print("#"*10)

    my_range3 = range(1,6,2)

    for i in my_range3:

    print(i)

    输出结果如下,我们都是使用 for 循环语句进行的输出,通过 list 函数也可以。

    0

    1

    2

    3

    ##########

    1

    2

    3

    ##########

    1

    3

    5

    range 函数在后续的编程中属于常用函数,很多场景下都需要借助它生成一个等差序列,所以该函数请牢牢掌握。所谓掌握的意思就是现在你需要好好的打一打代码。

    5.3 for 循环补充知识

    5.3.1 for 循环嵌套

    一个循环中的代码块嵌套另一个循环称为循环的嵌套,在编写循环嵌套代码的时候需要注意。

    代码块的缩进一定要留意,核对好代码块属于哪个 for 循环

    解析来是一个经典案例,当年橡皮擦学习的时候就在这里废了很大力气,一直到期末考试也没弄明白,入门阶段这应该比较难理解的程序了,通过 Python 输出一个九九乘法表。

    for i in range(1,10):

    for j in range(1,10):

    print("%d*%d=%3d"%(i,j,i*j),end=" ")

    print(" ")

    代码运行之后如下图所示:

    这个程序包含了 for 循环,for 循环嵌套,格式化输出字符串,还有不同级别的缩进。 循环在执行的时候,你可以先这么理解,外层循环转 1 遍,内层循环跑 1 圈。

    这句话的含义初学到这个阶段,很难理解,这是啥意思?很多教材可能会写流程图,告诉你分支怎么走,怎么走。很费劲,在橡皮擦看来这是个顿悟的事情。

    在上述代码中标记两条线。

    外层循环就是说的最上面的循环,它循环一次,里面的循环,就是包含变量 j 的那个 for 循环,要循环 1 圈,就是都循环一遍。 那结论就出来了。当 i = 1 的时候,j 从 1 一直变到 10,然后在输出一个 print(" ");

    当 i=2 的时候,i 还是要从 1 变到 10,然后在输出一个 print(" ");

    当 i=3 的时候...,然后在输出一个 print(" ")

    i=4 的时候,然后在输出一个 print(" ")

    当 i=9 的时候,内层循环循环完最后一圈。所有的循环都运行完毕,结束该程序。

    特别说明一下 print 函数输出的时候,默认会带一个 \n,之前的课程已经学习了,该符号代表换行。如果想去掉 print 函数自带的换行符,需要使用 end 参数,即 print("待输出内容",end=" ")。

    放心,虽然我详细的说了一遍流程,能悟了的同学就地就悟了,看不懂还是看不懂,这个地方确实很难(难吗?),不过不用担心,随着写代码越来越多,慢慢的你就会了,不会写这个也不影响后续的学习,总之多写两遍就懂了。

    5.3.2 break 终止循环

    终止循环你就这么理解,当满足某个条件的时候,我不想循环了,这就是 break 的使用场景,当满足某个条件这肯定用到的是 if 语句。

    例如,当循环一个列表的时候,如果出现一个大于 3 的数字,那终止循环,代码如下:

    for i in range(1,10):

    if i > 3 :

    print("出现大于3的数字,终止循环")

    break

    5.3.3 continue 继续循环

    continue 与 break 类似,都是当满足某个条件时,要做的事情,只不过程序碰到 continue 关键字,不是终止循环,而是进入下一次循环,当前循环不管还剩下什么工作,不做了。

    for i in range(0,5):

    if i > 3 :

    continue

    print("当前数字为:",i)

    上述代码中在 for 循环存在一个 if 判断,当 i>3 的时候,也就是列表中数字大于 3,直接进入下一次循环,这样导致一个事情就是在循环中发现比 3 大的数字之后,print 就不会执行了,所以运行代码会发现下述结果,只显示小于等于 3 的数字。

    当前数字为: 0

    当前数字为: 1

    当前数字为: 2

    当前数字为: 3

    5.3.4 for ... else 循环

    for ... else 循环是 Python 中一种特定的语法结构,大白话就是当 for 循环执行完毕了就执行 else。很多时候大白话能理解了,你能用来描述清楚这个是干啥,这个知识点其实已经掌握了,初学阶段没必要咬文嚼字的。

    例如测试下述代码:

    for i in range(0,5):

    if i > 3 :

    continue

    print("当前数字为:",i)

    else:

    print("不管上面的 for 循环干了啥,我都要执行一次")

    在这里其实有个知识点需要补充下,就是代码配对的问题,啥叫配对,if 和 else 就是一对,为什么会有这种说法呢,参见下述代码:

    if 条件:

    pass

    if 条件:

    pass

    else:

    pass

    pass 表示占位,在 Python 中是支持该关键字的,就是还没想清楚这里写啥代码,先弄个单词放着占住位置。

    上面的代码出现了两个 if 和一个 else,一定要注意,else 和最近的 if 是一对,最上面的 if 就是一个普通的 if。这种问题在代码嵌套的时候会更加有意思。

    if 条件:

    pass

    if 条件:

    if 条件:

    pass

    else:

    pass

    else:

    pass

    依据缩进关系,你要找好 if 与 else 哪个是一对显得非常重要了。肉眼看不出来就实际敲敲键盘。

    综合刚学习的内容,现在你知道如何对 for else 进行配对了吗?

    5.4 while 循环

    while 循环也是 Python 中的一种循环语法,不过这种循环很容易搞成死循环,就是一直循环下去到电脑崩溃,死循环有坏处但也有它的应用场景,后面咱也会学习到。

    while 循环的语法格式如下:

    while 条件:

    代码块

    格式中条件非常重要,这个条件运算之后需要判断真假,为真(True)才会进入到 while 中的代码块运行程序。

    5.4.1 while 循环的经典应用

    while 循环除了语法结构与 for 循环有差异以外,很多地方基本一致,接下来完成一个通过 while 循环实现的经典案例 - 猜数字,这个勉强算是一个游戏。

    # 最终的答案为 12,其实可以用随机数

    answer = 12

    # 用户猜的数字

    guess = 0

    # 条件为 判断 guess 不等于 answer

    while guess!=answer:

    guess = int(input("请输入一个 1~100 之间的数字:"))

    if guess > answer:

    print("你的数字大了")

    elif guess < answer:

    print("你的数字小了")

    else:

    print("恭喜猜对,数字为 12 ")

    该案例虽然小,但是整合了很多之前学过的知识,例如 input 获取用户输入,int 将字符串转换成整数,if...elif...else 语句等内容,越是简单的知识点在后续的课程中出现越频繁,一定要注意基础最重要。

    5.4.2 while 其他说明

    while 循环的使用与 for 循环基本一致,很多时候你甚至可以看成是一回事。因为 break 与 continue 语句同样适用于 while 循环,这里不再做重复知识点的说明,后面进入复杂编码的时候,自然可以掌握。

    5.5 这篇博客的总结

    循环也属于 Python 中的基本语法结构,分支与循环学习完毕之后,在加上最基本的顺序执行,那对于编程来说已经足够完成很多任务了,你也可以在想想,现实世界还有没有其它解决问题的路径方式,如果得到的答案是没有,其实程序开发也就这点事儿了。

    不过我也是从新手走来,现在看这些知识 so easy ~,但是第一次学习的时候,还是发出了这是啥,咋回事,怎么就实现了的灵魂问题,不用太担心,眼睛停下,手动起来,敲一敲键盘就可以了。

    编程没有难点,难的是按键盘的速度。

    本篇讲了 range 函数,但是橡皮擦省略了 列表生成器部分因为这个阶段学习有点难了,后面的课程会将其补齐。

    最后一碗毒鸡汤

    没有钱包的充实,哪来内心的宁静。 O(∩_∩)O 哈哈~

    想学Python爬虫,可以订阅橡皮擦专栏哦~ 点击发现惊喜

    今天是持续写作的第 4/100 天。 如果你有想要交流的想法、技术,欢迎在评论区留言。如果你想跟博主建立亲密关系,可以关注博主,或者关注博主公众号“非本科程序员”,了解一个非本科程序员是如何成长的。 博主 ID:梦想橡皮擦,希望大家点赞、评论、收藏。

    展开全文
  • )MST(M代码,T代码,S代码全部可以跟在后面)G71P1(P后面随便跟个数字,代表循环开始的第一阶段程序)Q2(P后面随便跟个数字,代表循环开始的最后一段程序)U0.2(精车留着的余量,这个U代表X轴)W0.2(Z轴精加工余量,这个...

    我来解说吧, 半夜无聊码字玩!~

    G71 U1(每次吃刀量)  R0.5(每次退刀量)F(F值了,看你用G98还是G99,自己给数值。)MST

    (M代码,T代码,S代码全部可以跟在后面)

    G71 P1(P后面随便跟个数字,代表循环开始的第一阶段程序)Q2(P后面随便跟个数字,代表循环开始的最后一段程序) U0.2(精车留着的余量,这个U代表X轴) W0.2(Z轴精加工余量,这个W代表Z轴)

    N1 G0  X。。。。。

    G1Z-。。。。。

    N2 X。。。。

    G70 P1 Q2 (此程序代表精车把路线从N1---N2再走一次)

    下面给你仿真个

    G99

    G0 X100 Z100

    M03 S500

    G0 X42 Z2 M08

    G71 U2 R0.5 F0.2

    G71 P1 Q2 U0.2 W0.2

    N1 G0 X0

    G1 X20 F0.1

    Z-20

    X30 R3

    N2 Z-30

    G70 P1 Q2

    M05

    G0 X100 Z100 m09

    M30

    码字好累!!!!!

    展开全文
  • 长文,要有耐心为什么单线程是一个限制?当调用堆栈中有函数调用需要花费大量时间来处理时会发生什么?例如,假设在浏览器中运行一个复杂的图像转换算法。...JavaScript程序的构建块你可能在单个.js文件中编写 JavaSc...
    长文,要有耐心

    为什么单线程是一个限制?

    当调用堆栈中有函数调用需要花费大量时间来处理时会发生什么?

    例如,假设在浏览器中运行一个复杂的图像转换算法

    当调用堆栈有函数要执行时,浏览器不能做任何其他事情——它被阻塞了。这意味着浏览器不能渲染,不能运行任何其他代码,只是卡住了。那么你的应用 UI 界面就卡住了,用户体验也就不那么好了。

    JavaScript程序的构建块

    你可能在单个.js文件中编写 JavaScript 应用程序,但可以肯定的是,你的程序由几个块组成,其中只有一个正在执行,其余的将在稍后执行。最常见的块单元是函数。

    大多数刚接触JavaScript的开发人员似乎都有这样的问题,就是认为所有函数都是同步完成,没有考虑的异步的情况。如下例子:

    587ccd6154015a7d0e2e4e50f10a7f4b.png

    你可能知道标准 Ajax 请求不是同步完成的,这说明在代码执行时 Ajax(..) 函数还没有返回任何值来分配给变量 response。

    一种等待异步函数返回的结果简单的方式就是 回调函数:

    c4276c68a10f5c71cc1454b8255221f9.png

    注意:实际上可以设置同步Ajax请求,但永远不要那样做。如果设置同步Ajax请求,应用程序的界面将被阻塞——用户将无法单击、输入数据、导航或滚动。这将阻止任何用户交互,这是一种可怕的做法。

    以下是同步 Ajax 地,但是请千万不要这样做:

    e2890eb3a9cc69648b9798b59ac6e6ac.png

    这里使用Ajax请求作为示例,你可以让任何代码块异步执行。

    这可以通过 setTimeout(callback,milliseconds) 函数来完成。setTimeout 函数的作用是设置一个回调函数milliseconds后执行,如下:

    function first() { console.log('first');}function second() { console.log('second');}function third() { console.log('third');}first();setTimeout(second, 1000); // Invoke `second` after 1000msthird();

    输出:

    firstthirdsecond

    解析事件循环

    这里从一个有点奇怪的声明开始——尽管允许异步 JavaScript 代码(就像上例讨论的setTimeout),但在ES6之前,JavaScript本身实际上从来没有任何内置异步的概念,JavaScript引擎在任何给定时刻只执行一个块。

    那么,是谁告诉JS引擎执行程序的代码块呢?实际上,JS引擎并不是单独运行的——它是在一个宿主环境中运行的,对于大多数开发人员来说,宿主环境就是典型的web浏览器或Node.js。实际上,现在JavaScript被嵌入到各种各样的设备中,从机器人到灯泡,每个设备代表 JS 引擎的不同类型的托管环境。所有环境中的共同点是一个称为事件循环的内置机制,它处理程序的多个块在一段时间内通过调用JS引擎的执行。

    这意味着JS引擎只是任意JS代码的按需执行环境,是宿主环境处理事件运行及结果。

    例如,当 JavaScript 程序发出 Ajax 请求从服务器获取一些数据时,在函数(“回调”)中设置“response”代码,JS引擎告诉宿主环境:"我现在要推迟执行,但当完成那个网络请求时,会返回一些数据,请回调这个函数并给数据传给它"。

    然后浏览器将侦听来自网络的响应,当监听到网络请求返回内容时,浏览器通过将回调函数插入事件循环来调度要执行的回调函数。以下是示意图:

    04a243e9e7c185e85090e9bd6ab3ce11.png

    这些Web api是什么?从本质上说,它们是无法访问的线程,只能调用它们。它们是浏览器的并发部分。

    这样的迭代在事件循环中称为(tick)标记,每个事件只是一个函数回调。

    293e3a5917438c0ae61a37617b93a86a.png

    让我们“执行”这段代码,看看会发生什么:

    1.初始化状态都为空,浏览器控制台是空的的,调用堆栈也是空的

    a824fa3188f5297fa30e75048ae3a8bd.png

    2. console.log('Hi')添加到调用堆栈中

    a1648531aec6db1777125b2c30617ad0.png

    3. 执行console.log('Hi')

    68a03cedfd409cd44dd3ba17be7c0947.png

    4. console.log('Hi')从调用堆栈中移除。

    b871fcf3c50b94eb3ae975cbe5373fa2.png

    5. setTimeout(function cb1() { ... }) 添加到调用堆栈。

    66b587950b3209dd6b02922e37d592a5.png

    6. setTimeout(function cb1() { ... }) 执行,浏览器创建一个计时器计时,这个作为Web api的一部分。

    904a94e11c53e9ffb9154110f251783c.png

    7. setTimeout(function cb1() { ... })本身执行完成,并从调用堆栈中删除。

    3f3d8b4535f7ce19cdf33b19ae620082.png

    8. console.log('Bye') 添加到调用堆栈

    cc7541a1e99d6ffe4d0f4025f5a23b91.png

    9. 执行 console.log('Bye')

    667070881b9e27866e0b557117d80382.png

    10. console.log('Bye') 从调用调用堆栈移除

    f2b505c688994eb819984c81915ca88b.png

    11. 至少在5秒之后,计时器完成并将cb1回调推到回调队列。

    1287620a902283270116bf8fa3cce4a6.png

    12. 事件循环从回调队列中获取cb1并将其推入调用堆栈。

    b68770ed02b6731ae4cf31a75c96fbe7.png

    13. 执行cb1并将console.log('cb1')添加到调用堆栈。

    1ab69e5809dbc54d6ca12a19f0e0a698.png

    14. 执行 console.log('cb1')

    74c3691d405b94ec918a1be47cc909f9.png

    15. console.log('cb1') 从调用堆栈中移除

    d52cb3e3114a59b3afec9e7257d8bf37.png

    16. cb1 从调用堆栈中移除

    be82f26fa31b05962bcadb6f9f3e7c7d.png

    快速回顾:

    8bfaf92890421fb8cf58f16ae0033d03.gif

    值得注意的是,ES6指定了事件循环应该如何工作,这意味着在技术上它属于JS引擎的职责范围,不再仅仅扮演宿主环境的角色。这种变化的一个主要原因是ES6中引入了 Promises,因为ES6需要对事件循环队列上的调度操作进行直接、细度的控制。

    setTimeout(…) 是怎么工作的

    需要注意的是,setTimeout(…)不会自动将回调放到事件循环队列中。它设置了一个计时器。当计时器过期时,环境将回调放到事件循环中,以便将来某个标记(tick)将接收并执行它。请看下面的代码:

    setTimeout(myCallback, 1000);

    这并不意味着myCallback将在1000毫秒后就立马执行,而是在1000毫秒后,myCallback被添加到队列中。但是,如果队列有其他事件在前面添加回调刚必须等待前后的执行完后在执行myCallback。

    有不少的文章和教程上开始使用异步JavaScript代码,建议用setTimeout(回调,0),现在你知道事件循环和setTimeout是如何工作的:调用setTimeout 0毫秒作为第二个参数只是推迟回调将它放到回调队列中,直到调用堆栈是空的。

    请看下面的代码:

    console.log('Hi');setTimeout(function() { console.log('callback');}, 0);console.log('Bye');

    虽然等待时间被设置为0 ms,但在浏览器控制台的结果如下:

    HiByecallback

    ES6的任务队列是什么?

    ES6中引入了一个名为“任务队列”的概念。它是事件循环队列上的一个层。最为常见在Promises 处理的异步方式。

    想像一下:任务队列是一个附加到事件循环队列中每个标记末尾的队列。某些异步操作可能发生在事件循环的一个标记期间,不会导致一个全新的事件被添加到事件循环队列中,而是将一个项目(即任务)添加到当前标记的任务队列的末尾。

    这意味着可以放心添加另一个功能以便稍后执行,它将在其他任何事情之前立即执行。

    任务还可能创建更多任务添加到同一队列的末尾。理论上,任务“循环”(不断添加其他任务的任等等)可以无限运行,从而使程序无法获得转移到下一个事件循环标记的必要资源。从概念上讲,这类似于在代码中表示长时间运行或无限循环(如while (true) ..)。

    回调

    正如你已经知道的,回调是到目前为止JavaScript程序中表达和管理异步最常见的方法。实际上,回调是JavaScript语言中最基本的异步模式。无数的JS程序,甚至是非常复杂的程序,除了一些基本都是在回调异步基础上编写的。

    然而回调方式还是有一些缺点,许多开发人员都在试图找到更好的异步模式。但是,如果不了解底层的内容,就不可能有效地使用任何抽象出来的异步模式。

    嵌套回调

    请看以下代码:

    1f646fe4aacc611aa7ba4c65fda90ad3.png

    有一个由三个函数组成的链嵌套在一起,每个函数表示异步系列中的一个步骤。

    这种代码通常被称为“回调地狱”。但是“回调地狱”实际上与嵌套/缩进几乎没有任何关系,这是一个更深层次的问题。

    首先,我们等待“单击”事件,然后等待计时器触发,然后等待Ajax响应返回,此时可能会再次重复所有操作。

    乍一看,这段代码似乎可以将其异步性自然地对应到以下顺序步骤:

    listen('click', function (e) { // ..});

    然后:

    setTimeout(function(){ // ..}, 500);

    接着:

    ajax('https://api.example.com/endpoint', function (text){ // ..});

    最后:

    if (text == "hello") { doSomething();}else if (text == "world") { doSomethingElse();}

    因此,这种连续的方式来表示异步代码似乎更自然.

    Promises

    请看下面的代码:

    var x = 1;var y = 2;console.log(x + y);

    这非常简单:它对x和y的值进行求和,并将其打印到控制台。但是,如果x或y的值丢失了,仍然需要求值,要怎么办?

    例如,需要从服务器取回x和y的值,然后才能在表达式中使用它们。假设我们有一个函数loadX和loadY,它们分别从服务器加载x和y的值。然后,一旦x和y都被加载,假设我们有一个函数sum,它对x和y的值进行求和。

    它可能看起来像这样:

    53dfde23e52d45656d1155a09cf87abd.png

    这里有一些非常重要的事情——在这个代码片段中,我们将x和y作为异步获取的的值,并且执行了一个函数sum(…)(从外部),它不关心x或y,也不关心它们是否立即可用。

    当然,这种基于回调的粗略方法还有很多不足之处。 这只是一个我们不必判断对于异步请求的值的处理方式一个小步骤而已。

    Promise Value

    用Promise来重写上例:

    4e1bae8d559991a55d139901b1cee47d.png

    在这个代码片段中有两层Promise。

    fetchX 和 fetchY 先直接调用,返回一个promise,传给 sum。 sum 创建并返回一个Promise,通过调用 then 等待 Promise,完成后,sum 已经准备好了(resolve),将会打印出来。

    第二层是 sum(…) 创建的 Promise ( 通过 Promise.all([ ... ]) )然后返回 Promise,通过调用then(…)来等待。当 sum(…) 操作完成时,sum 传入的两个 Promise 都执行完后,可以打印出来了。这里隐藏了在sum(…)中等待x和y未来值的逻辑。

    注意:在sum(...)内,Promise.all([...])调用创建一个 promise(等待 promiseX 和 promiseY 解析)。 然后链式调用 .then(...)方法里再的创建了另一个 Promise,然后把 返回的 x 和 和(values[0] + values[1]) 进行求和 并返回 。

    因此,我们在sum(...)末尾调用then(...)方法 — 实际上是在返回的第二个 Pwwromise 上运行,而不是由Promise.all([ ... ])创建 Promise。 此外,虽然没有在第二个 Promise 结束时再调用 then方法 ,其时这里也创建一个 Promise。

    Promise.then(…) 实际上可以使用两个函数,第一个函数用于执行成功的操作,第二个函数用于处理失败的操作:

    如果在获取x或y时出现错误,或者在添加过程中出现某种失败,sum(…) 返回的 Promise将被拒绝,传递给 then(…) 的第二个回调错误处理程序将从 Promise 接收失败的信息。

    从外部看,由于 Promise 封装了依赖于时间的状态(等待底层值的完成或拒绝,Promise 本身是与时间无关的),它可以按照可预测的方式组成,不需要开发者关心时序或底层的结果。一旦 Promise 决议,此刻它就成为了外部不可变的值。

    可链接调用 Promise 真的很有用:

    创建一个延迟2000ms内完成的 Promise ,然后我们从第一个then(...)回调中返回,这会导致第二个then(...)等待 2000ms。

    注意:因为Promise 一旦被解析,它在外部是不可变的,所以现在可以安全地将该值传递给任何一方,因为它不能被意外地或恶意地修改,这一点在多方遵守承诺的决议时尤其正确。一方不可能影响另一方遵守承诺决议的能力,不变性听起来像是一个学术话题,但它实际上是承诺设计最基本和最重要的方面之一,不应该被随意忽略。

    使用 Promise 还是不用?

    关于 Promise 的一个重要细节是要确定某个值是否是一个实际的Promise 。换句话说,它是否具有像Promise 一样行为?

    我们知道 Promise 是由new Promise(…)语法构造的,你可能认为 p instanceof Promise是一个足够可以判断的类型,嗯,不完全是。

    这主要是因为可以从另一个浏览器窗口(例如iframe)接收 Promise 值,而该窗口或框架具有自己的 Promise 值,与当前窗口或框架中的 Promise 值不同,所以该检查将无法识别 Promise 实例。

    此外,库或框架可以选择性的封装自己的 Promise,而不使用原生 ES6 的Promise 来实现。事实上,很可能在老浏览器的库中没有 Promise。

    吞掉错误或异常

    如果在 Promise 创建中,出现了一个javascript一场错误(TypeError 或者 ReferenceError),这个异常会被捕捉,并且使这个 promise 被拒绝。

    但是,如果在调用 then(…) 方法中出现了 JS 异常错误,那么会发生什么情况呢?即使它不会丢失,你可能会发现它们的处理方式有点令人吃惊,直到你挖得更深一点:

    4ec73084ae005300a4492a7f9d5622e6.png

    看起来foo.bar()中的异常确实被吞噬了,不过,它不是。然而,还有一些更深层次的问题,我们没有注意到。 p.then(…) 调用本身返回另一个 Promise,该 Promise 将被 TypeError 异常拒绝。

    处理未捕获异常

    许多人会说,还有其他更好的方法。

    一个常见的建议是,Promise 应该添加一个 done(…),这实际上是将 Promise 链标记为 “done”。done(…) 不会创建并返回 Promise ,因此传递给 done(..) 的回调显然不会将问题报告给不存在的链接 Promise 。

    Promise 对象的回调链,不管以 then 方法或 catch 方法结尾,要是最后一个方法抛出错误,都有可能无法捕捉到(因为 Promise 内部的错误不会冒泡到全局)。因此,我们可以提供一个 done 方法,总是处于回调链的尾端,保证抛出任何可能出现的错误。

    b36e3a174e8aba9f3b583d8e74c5240e.png

    ES8中改进了什么 ?Async/await (异步/等待)

    JavaScript ES8引入了 async/await,这使得使用 Promise 的工作更容易。这里将简要介绍async/await 提供的可能性以及如何利用它们编写异步代码。

    使用 async 声明异步函数。这个函数返回一个 AsyncFunction 对象。AsyncFunction 对象表示该函数中包含的代码的异步函数。

    调用使用 async 声明函数时,它返回一个 Promise。当这个函数返回一个值时,这个值只是一个普通值而已,这个函数内部将自动创建一个承诺,并使用函数返回的值进行解析。当这个函数抛出异常时,Promise 将被抛出的值拒绝。

    使用 async 声明函数时可以包含一个 await 符号,await 暂停这个函数的执行并等待传递的 Promise 的解析完成,然后恢复这个函数的执行并返回解析后的值。

    async/wait 的目的是简化使用承诺的行为

    让看看下面的例子:

    function getNumber1() { return Promise.resolve('374');}// 这个函数与getNumber1相同async function getNumber2() { return 374;}

    类似地,抛出异常的函数等价于返回被拒绝的 Promise 的函数:

     function f1() { return Promise.reject('Some error');}async function f2() { throw 'Some error';}

    await 关键字只能在异步函数中使用,并允许同步等待 Promise。如果在 async 函数之外使用 Promise,仍然需要使用 then 回调:

    4242870001d7b7dae4a00b632d25ff88.png

    还可以使用“异步函数表达式”定义异步函数。异步函数表达式与异步函数语句非常相似,语法也几乎相同。异步函数表达式和异步函数语句之间的主要区别是函数名,可以在异步函数表达式中省略函数名来创建匿名函数。异步函数表达式可以用作生命(立即调用的函数表达式),一旦定义它就会运行。

    76344434a3451cd4b03a6708989953b0.png

    更重要的是,在所有主流的浏览器都支持 async/await:

    5433044eb5ea525de0be13ed40c7f573.png

    编写高度可维护性、非易碎异步代码的5个技巧

    1、简介代码: 使用 async/await 可以编写更少的代码。 每次使用 async/await时,都会跳过一些不必要的步骤:使用.then,创建一个匿名函数来处理响应,例如:

    316f30fad702c0523e7ede8ad19e9d2f.png

    2、错误处理: Async/wait 可以使用相同的代码结构(众所周知的try/catch语句)处理同步和异步错误。看看它是如何与 Promise 结合的:

    d84804131e66f0853b83ac3dd96b1202.png

    3、条件:用async/ wait编写条件代码要简单得多:

    59425d2eb8166c780910bfbc44684ace.png

    00527601a2b4dd4cef93b3c1be46b88b.png

    4、堆栈帧:与 async/await不同,从 Promise 链返回的错误堆栈不提供错误发生在哪里。看看下面这些:

    6f7bec60daeedd7e70654aed74ff7459.png

    与:

    0328f5ddc6054eab06851ef76dfbb5b9.png

    5.调试:如果你使用过 Promise ,那么你知道调试它们是一场噩梦。例如,如果在一个程序中设置了一个断点,然后阻塞并使用调试快捷方式(如“停止”),调试器将不会移动到下面,因为它只“逐步”执行同步代码。使用async/wait,您可以逐步完成wait调用,就像它们是正常的同步函数一样。


    欢迎关注
    展开全文
  • 7.5 free和delete把指针怎么啦? 50 7.6 动态内存会被自动释放吗? 50 7.7 杜绝“野指针” 51 7.8 有了malloc/free为什么还要new/delete ? 52 7.9 内存耗尽怎么办? 53 7.10 malloc/free 的使用要点 54 7.11 new/...
  •  游戏循环可以说是游戏编程模式中的精髓,几乎所有的游戏都包含它,相比而言,那些非游戏的程序却很难见它的踪影。这是为什么了?原因在于交互。  解释之前我们先回想一下早期的程序员的工作方式:他们先写好程序...
  • 写重复代码 是可耻的行为-------------- 完美的分割线 --------------程序在一般情况下是按顺序执行的,编程语言提供了各种控制结构,允许更复杂的执行路径。循环(loop)用于解决重附代码的问题循环语句允许我们用...
  • 我不知道如何循环代码,也不知道如何存储数据,如果我输入一个硬币,能够不断增加银行硬币总数。我只能这样做,它运行并告诉我,如果我加上,例如,100便士,我的银行有100便士。但是它会重新设置。我该怎么做?我的...
  • 我决定告诉你如何编写可怕的...差一错误(英语:Off-by-one error,缩写 OBOE,是在计数时由于边界条件判断失误导致结果多了一或少了一的错误,通常指计算机编程循环多了一次或者少了一次的程序错误,属于逻辑错误...
  • 抖音上火了的表白代码,小伙伴们知道这个表白代码怎么写的吗?虽然大家都知道是使用vbs实现的!小编也承让VBS实现更简单,但是如果把打印心那个程序用起来,[C语言]是反而更妙一点。今天小编带着大家用C语言实现下...
  • 怎么合理使用for循环?for循环编程语言中一种循环语句,是Java程序员日常工作中的重要组成部分。循环语句由循环体及循环的判定条件两部分组成,其表达式为:for(单次表达式;条件表达式;末尾循环体){中间循环体;}。...
  • 怎么样解决Scratch程序中的BUG问题? 一、如何尽量避免BUG 1、思路清晰:无论使用任何工具,我们在设计代码模块的时候,我们都应当尽量理清自己的思路,用尽量简洁的方式来实现想要的功能,或者使用模块化的方法来...
  • C语言的一个程序怎么执行的

    千次阅读 2014-10-15 00:40:10
    提到一个程序怎么执行,那么很多人就会说,一行代码一行代码的执行嘛。 是,在面向过程的编程中,代码是从main函数开始,到执行完毕; 但是面向对象就不仅仅是这样了,这里不讨论。 一个C语言程序的执行...
  • 一起复习一下吧~函数有3个好处:更容易看清代码意图更容易对需求变化做出反应(改变)更容易减少程序bug除了函数,减少重复代码的另一种工具是迭代,它的作用在于可以对多个输入执行同一种处理,比如对多个列或多个...
  • 做成能够循环播放的程序。通过button实现。但是通过其他博主的方式,很难做到这个要求,只会将少数个图片单独放进程序里进行逐一显示,并没有采用到for循环,这很不便利。 <code>from ...
  • 编C语言一般都用啊还有\xCD是C语言Ascii代码 表示一个图形用循环32313133353236313431303231363533e58685e5aeb931333264643133语句啊!等我一下 晚上写出来 贴上哦晚上10:00 上完课回来呵呵 分给不给 随便 你的问题...
  • C++程序设计语言(特别版)--源代码

    热门讨论 2012-04-23 07:33:51
    提供的是书中的源代码,非课后练习源代码。 本版本是高清版,是第1版第18次印刷,是书签最全最好的版本。 基本信息 原书名: The C++ Programming Language, Special Edition 原出版社: Addison Wesley 作者: ...
  • 提供的是本书的课后习题源代码,也就是《C++程序设计语言(特别版)题解》的源代码。非书中源代码。 本版本是高清版,是第1版第18次印刷,是书签最全最好的版本。 基本信息 原书名: The C++ Programming Language...
  • 6.4.4 unicode怎么样? 6.4.5 truetype和大字体 6.5 插入符(不是光标) 6.5.l 插入符函数 6.5.2 typer 程序 第七章 鼠标 7.1 鼠标基础 7.1.1 一些简单的定义 7.2 客户区鼠标消息 7.2.l ...
  • 前言我们知道Javascript语言的执行环境是"单线程"。也就是指一次只能完成一件任务。...常见的浏览器无响应(假死),往往就是因为某一段Javascript代码长时间运行(比如死循环),导致整个页面卡在这个地方...
  • 编程语言

    2018-08-11 11:22:02
    编程语言的核心,基本都包含了以下内容: 数据类型 表达式 变量及赋值 分支和循环 函数和函数调用 类和包 而自然语言的组成大致如下: 单词 短语 连词、介词 语句 段落 文章、书籍 一篇文章讲了一个故事,一...
  • 学好编程需要英语很好吗

    千次阅读 2019-08-16 10:56:04
    学会编程不需要多高深的英语水平,想要学会编程,简单的英语水平足够了,现在的程序开发环境又很友好,基本上打开之后不需要怎么配置,直接写代码就行,程序语言无外乎顺序、判断和循环语句,写一写简单的程序毫无...
  • C语言编程要点

    2017-09-18 00:10:37
    8.7. 在程序退出main()函数之后,还有可能执行一部分代码吗? 135 8.8. 用PASCAL修饰符说明的函数与普通C函数有什么不同? 136 8.9. exit()和return有什么不同? 136 第9章 数 组 137 9.1. 数组的下标总是从0开始吗? ...
  • 现在的程序开发环境又很友好,基本上打开之后不需要怎么配置,直接写代码就行,程序语言无外乎顺序、判断和循环语句,写一写简单的程序毫无压力,所以需要记住的英文其实并不多。 为什么这么说呢?我们拿Java和...
  • 现在的程序开发环境又很友好,基本上打开之后不需要怎么配置,直接撸代码就行,程序语言无外乎顺序、判断和循环语句,写一写简单的程序毫无压力,所以需要记住的英文其实并不多。 为什么这么说呢?我们以C++和Python...
  • 学会编程不需要多高深的英语水平,想要学会编程,简单的英语水平足够了,现在的程序开发环境又很友好,基本上打开之后不需要怎么配置,直接写代码就行,程序语言无外乎顺序、判断和循环语句,写一写简单的程序毫无...
  • 现在的程序开发环境又很友好,基本上打开之后不需要怎么配置,直接写代码就行,程序语言无外乎顺序、判断和循环语句,写一写简单的程序毫无压力,所以需要记住的英文其实并不多。 PS:获取常用1800开发单词表:...
  • 现在的程序开发环境又很友好,基本上打开之后不需要怎么配置,直接写代码就行,程序语言无外乎顺序、判断和循环语句,写一写简单的程序毫无压力,所以需要记住的英文其实并不多。 为什么这么说呢?我们拿Java和...

空空如也

空空如也

1 2 3 4 5 ... 13
收藏数 250
精华内容 100
关键字:

代码循环程序怎么编程