当我们不知道函数的返回值或返回需要多长时间时,使用Promise是构建异步应用程序的好方法。它们使无需深层嵌套的回调即可更轻松地表达和推理异步操作的序列,并且它们支持类似于同步try...catch语句的错误处理方式。承诺适用于所有现代浏览器的最新版本

  • Promise定义
    • 举例一个视频聊天应用程序
  • 解释并实践Promise
    • 应对失败
    • 链接块
    • 创建自己的Promise

Promise定义

什么是Promise?
从本质上讲,Promise是表示操作中间状态的对象,实际上,它是将来会在某个时候返回某种结果的保证。不能保证确切地知道何时该操作将完成并返回结果,但是可以保证当结果可用或诺言失败时,将执行您提供的代码,以便用成功的结果,或妥善处理失败案例。

一般情况下,你是不感兴趣的时间异步操作将返回其结果量(当然,除非它需要远远太长!),更感兴趣的是能够响应它返回,只要那是。当然,它不会阻塞其余的代码执行也很好。

举例一个视频聊天应用程序

该功能通过使用一个名为setStatusMessage()“ Calling …”的消息来更新状态显示的函数来开始,该消息表示正在尝试进行呼叫。然后getUserMedia(),它呼叫,要求同时具有视频和音频轨道的流,然后获取该流,然后设置视频元素以将来自摄像机的流显示为“自视图”,然后获取该流的每个轨道并将它们添加到WebRTC, RTCPeerConnection代表与另一个用户的连接。之后,状态显示更新为“已连接”。

如果getUserMedia()失败,则该catch块运行。这用于setStatusMessage()更新状态框以指示发生了错误。

这里重要的是getUserMedia(),即使尚未获取摄像机流,呼叫也几乎立即返回。即使handleCallButton()函数已经返回调用它的代码,当getUserMedia()工作完成时,它也会调用您提供的处理程序。只要应用程序不认为流媒体已经开始,它就可以继续运行。

function handleCallButton(evt) {setStatusMessage("Calling...");navigator.mediaDevices.getUserMedia({video: true, audio: true}).then(chatStream => {selfViewElem.srcObject = chatStream;chatStream.getTracks().forEach(track => myPeerConnection.addTrack(track, chatStream));setStatusMessage("Connected");}).catch(err => {setStatusMessage("Failed to connect");});
}

解释并实践Promise

使用该方法从Web上获取图像,该blob()方法将获取响应的原始内容转换为Blob对象,然后在<img>元素内部显示该Blob 。

调用该fetch()方法,并将要传递给网络的图像URL作为参数传递给该方法。这也可以将options对象作为可选的第二个参数,但是我们现在仅使用最简单的版本。我们将存储在fetch()称为的变量内部返回的Promise对象promise

let promise = fetch('coffee.jpg');

为了响应成功完成的操作(在这种情况下,当Response返回a时),我们调用.then()promise对象的方法。内部的回调.then()块(简称执行人),只有当承诺调用成功完成,并返回运行Response中的承诺发言,当它已经-对象实现。将返回的Response对象作为参数传递给它。

注意:.then()块的工作方式类似于使用来将事件侦听器添加到对象时AddEventListener()。直到事件发生时(诺言履行时),它才会运行。最显着的区别是,.then()每次使用a时,它将只运行一次,而事件侦听器可以多次调用。

我们立即在此响应上运行该方法,以确保完整下载了响应主体,并在可用时将其转换为Blob可以处理的对象。这样返回的结果如下:

response => response.blob()
function(response) {return response.blob();
}

提取承诺不会因404或500错误而失败-只会在诸如网络故障之类的灾难性事件上失败。相反,它们成功了,但response.ok属性设置为false。例如,要在404上产生错误,我们需要检查的值response.ok,如果false抛出错误,则仅返回blob(如果是)true。可以这样做-在JavaScript的第一行下面添加以下行。

let promise2 = promise.then(response => {if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);} else {return response.blob();}
});

每次致电.then()都会创建一个新的承诺。这非常有用;因为该方法还返回了一个Promise,所以我们可以通过调用.then()第二个Promise的方法来处理在实现时返回的对象。因为我们要对blob进行一些操作,而不是对它单独运行一个简单的方法并返回结果,所以这次我们需要将函数体用大括号括起来(否则会抛出错误)。

在代码末尾添加以下内容:

let promise3 = promise2.then(myBlob => {

})

正在运行URL.createObjectURL()方法,将其作为参数传递Blob给第二个Promise满足时返回。这将返回指向该对象的URL。然后,我们创建一个<img>元素,将其src属性设置为等于对象URL并将其附加到DOM,这样图像就会显示在页面上

填写执行程序函数的主体,在花括号内添加以下行:

let objectURL = URL.createObjectURL(myBlob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);

保存刚创建的HTML文件并将其加载到浏览器中,则会看到图像按预期显示在页面中。

应对失败

缺少某些内容-当前,如果其中一个诺言失败(拒绝,以诺言),则没有任何东西可以显式处理错误。我们可以通过.catch()根据先前的承诺运行方法来添加错误处理

要查看实际效果,请尝试将图像的URL拼写错误并重新加载页面。该错误将在浏览器开发人员工具的控制台中报告。

let errorCase = promise3.catch(e => {console.log('There has been a problem with your fetch operation: ' + e.message);
});

链接块

将.then()块(以及.catch()块)链接在一起,帮助您清楚地了解正在发生的事情

fetch('coffee.jpg')
.then(response => {if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);} else {return response.blob();}
})
.then(myBlob => {let objectURL = URL.createObjectURL(myBlob);let image = document.createElement('img');image.src = objectURL;document.body.appendChild(image);
})
.catch(e => {console.log('There has been a problem with your fetch operation: ' + e.message);
});

创建自己的Promise

使用Promise()构造函数
可以使用Promise()构造函数来构建自己的Promise 。您要执行此操作的主要情况是,您希望基于承诺不基于承诺的老式异步API编写代码。当您需要使用现有的,较旧的项目代码,库或框架以及现代的基于诺言的代码时,这非常方便。

resolve()并且reject()是你打电话履行或拒绝新创建的诺言功能。在这种情况下,promise将使用字符串“ Success!”来实现。

let timeoutPromise = new Promise((resolve, reject) => {setTimeout(function(){resolve('Success!');}, 2000);
});

因此,当您调用此Promise时,您可以将一个.then()块链接到它的末尾,并将其传递给字符串“ Success!”。在下面的代码中,我们只是警告该消息:

timeoutPromise
.then((message) => {alert(message);
})

甚至只是

timeoutPromise.then(alert);

拒绝自定义承诺
可以使用该reject()方法创建一个拒绝的承诺—就像resolve(),它采用单个值,但是在这种情况下,这是拒绝的原因,即,错误将传递到.catch()块中。

让我们扩展前面的示例,使其具有一些reject()条件,并允许在成功时传递不同的消息。

将两个参数传递给自定义函数-执行某项操作的消息以及执行该操作之前要经过的时间间隔。然后在函数内部,我们返回一个新Promise对象-调用该函数将返回我们要使用的承诺

function timeoutPromise(message, interval) {return new Promise((resolve, reject) => {if (message === '' || typeof message !== 'string') {reject('Message is empty or not a string');} else if (interval < 0 || typeof interval !== 'number') {reject('Interval is negative or not a number');} else {setTimeout(function(){resolve(message);}, interval);}});
};

在Promise构造函数内部,我们在if … else结构内部进行了一些检查:

首先,我们检查消息是否适合被警报。如果它是一个空字符串或根本不是一个字符串,我们会以适当的错误消息拒绝promise。
接下来,我们检查间隔是否为适当的间隔值。如果它是负数或不是数字,我们会以适当的错误消息拒绝诺言。
最后,如果两个参数都看起来都不错,则在使用指定的时间间隔后,我们将使用指定的消息来解决诺言setTimeout()。
由于该timeoutPromise()函数返回Promise,我们可以链.then(),.catch()等到它要利用它的功能。现在使用它- timeoutPromise用此替换以前的用法:

timeoutPromise('Hello there!', 1000)
.then(message => {alert(message);
})
.catch(e => {console.log('Error: ' + e);

回归前端学习第9天——JS的Promise承诺相关推荐

  1. web前端学习中CSS,JS代码压缩

    web前端要学习的知识有很多,前端基础要学习三个部分:HTML,CSS,JavaScript(简称JS),因此首先明确三个概念:HTML负责结构,网页想要表达的内容由html书写. CSS负责样式,网 ...

  2. web前端学习笔记之Node.js

    文章目录 01 浏览器中的JavaScript运行环境 02 什么是Node.js 03 安装Node.js 04 使用Node运行JS代码 05 fs模块 文件操作 05.1 什么是fs模块 05. ...

  3. 回归前端学习第22天-实现俄罗斯方块小游戏5(实现单机版1——结合HTML、CSS、JS来搭建界面)

    实现单机版俄罗斯方块小游戏,搭建页面 实现静态基础页面 实现静态基础页面 HTML: <!DOCTYPE html> <html lang="en">< ...

  4. 前端学习之路---node.js(二)

    知识点                                 下一篇    vue(一) 网站开发模型   + 黑盒子.哑巴   + 写代码让它变得更智能   + 按照你设计好的套路供用户使 ...

  5. 回归前端学习第24天-实现俄罗斯方块小游戏7(实现单机版3—实现消行、更新方块、结束)

    更改game.js.local.js. game.js中加入代码 使用下一个方块 设置到底部后,方块定住并换色 实现消行. 游戏结束 最后导出 整体代码 local.js代码 move函数更改 随机生 ...

  6. 回归前端学习第26天-实现俄罗斯方块小游戏9(实现单机版,一个计时带干扰的单机版俄罗斯方块小游戏完成)

    最终完善单机版俄罗斯方块小游戏,增加干扰功能--每10秒增加一行 增加干扰功能 game.js中加入addBotLine函数 local.js中加入 增加干扰功能 game.js中加入addBotLi ...

  7. 回归前端学习第25天-实现俄罗斯方块小游戏8(实现单机版4—设置计时、消行加分、游戏结束标志)

    增改game.js与local.js代码,实现对游戏的设置计时.消行加分.游戏结束标志等环节的设计 计时 计分 游戏结束 完整代码 local.js game.js 注意 计时 1.定义显示时间的di ...

  8. 回归前端学习第23天-实现俄罗斯方块小游戏6(实现单机版2——键盘控制方块移动)

    界面出现对应方块后,可自行控制其左右或快速下降的移动,上键可以实现方块形状的改变 调整代码结构 实现键盘控制方块移动 game.js中代码 注意这里在SquareFactory中又写了个make函数, ...

  9. 原创 回归前端学习第21天-实现俄罗斯方块小游戏3(深入了解Websocket~优化简易聊天室)

    对昨天的简易聊天室进行优化 增加一个mes对象,将传送的数据放在对象里 增加一个mes对象,将传送的数据放在对象里 wsServer.js中替换代码 broadcast(conn.nickname + ...

最新文章

  1. POJ-2635 The Embarrassed Cryptographer 大数取模
  2. 使用组策略实现文件复制
  3. php java memcached_php和java的memcached使用的兼容性问题解决过程
  4. 嵌入式开发中使用DDD进行调试
  5. 根据历史数据预测未来数据_未来销量预测——Kaggle基础方案(一):赛题背景和数据字段分析...
  6. 【Python】核酸结果统计难?复旦博士生的操作火了......
  7. C 语言实现数组冒泡排序
  8. 阮一峰:jQuery官方基础教程笔记
  9. 解析stm32的时钟
  10. Android-Universal-Image-Loader-master(图片浏览+缓存)
  11. 机器学习处理信号分离_【火炉炼AI】机器学习054-用ICA做盲源分离
  12. 学习python的字符串组合
  13. 医院信息科面试题和笔试题汇总(计算机相关专业)
  14. html 点击方块旋转,前端每日实战:86# 视频演示如何用纯 CSS 创作一个方块旋转动画...
  15. shell脚本的错误检测总结
  16. 采样频率和带宽的关系_磁共振成像带宽
  17. 织梦DedeCMS网站源代码分析详解
  18. Excel 图表与数据透视表制作
  19. 智能驾驶感知大战全面打响,谁在引领视觉技术的革新?
  20. hostapd.conf 解析

热门文章

  1. 用java自己实现代码阻塞的几种方式
  2. 自用 以后用得着 未完待续
  3. c语言printf啥意思,printf在c语言中的意思是什么呢
  4. 企业到底需要什么样的企业邮箱?
  5. SLC、MLC、TLC三者的区别
  6. 东华软件java笔试题以及答案_东华软件笔试
  7. MFC实现位图超链接代码
  8. 【C++】ODA的基本操作-平移、旋转、矩阵变换
  9. 【Unity Shader】2D模型 3D模型混用的穿模问题(Spine在3D场景中出现前后穿模问题的解决办法)
  10. 吴颖二:12.12 午夜金评 特朗普致力于通过税改计划演讲使美元指数暴涨