javascript中对象_了解JavaScript中的承诺

javascript中对象

我向您承诺,到本文结束时,您将更好地了解JavaScript。

我与JavaScript有一种“爱与恨”的关系。 但是尽管如此,JavaScript一直吸引着我。 在过去的10年中从事Java和PHP的工作之后,JavaScript看起来非常不同,但很有趣。 我没有花足够的时间在JavaScript上,并且一直在努力弥补这一点。

承诺是我遇到的第一个有趣的话题。 我一次又一次听到人们说Promises使您从Callback地狱中解救出来。 虽然这可能是一个令人愉快的副作用,但Promises还有很多,而这是我到目前为止能够弄清的。 这将是一篇长篇文章,如果您想突出显示某些部分,可以使用我们的扩展名http://bit.ly/highlights-extension

背景

当您第一次开始使用JavaScript时,可能会有些沮丧。 您会听到有人说JavaScript是同步编程语言,而其他人则说它是异步的。 您会听到阻塞代码,非阻塞代码,事件驱动的设计模式,事件生命周期,函数堆栈,事件队列,冒泡,polyfill,babel,angular,reactJS,vue JS以及大量其他工具和库。 不用。 您不是第一个。 也有一个术语。 这称为JavaScript疲劳 。 此推文很好地捕捉了它。

如果您想了解有关JavaScript疲劳的更多详细信息,请查看以下文章。 这篇文章在Hackernoon上获得42k拍手是有原因的:)

JavaScript是一种同步编程语言。 但是由于有了回调函数,我们可以使其像异步编程语言一样起作用。

外行的承诺

JavaScript中的承诺与您在现实生活中所做的承诺非常相似。 因此,首先让我们看看现实生活中的承诺。

字典中promise的定义如下

Promise :名词:确保某人会做某事或某件事会发生。

那么,当有人向你许诺时会发生什么呢?

  1. 一个承诺给您保证一定会做的事情。 他们(谁做出了承诺)是自己完成还是由他人完成,这并不重要。 他们给您保证,您可以据此计划。
  2. 诺言既可以兑现也可以兑现。
  3. 兑现诺言后,您会期望从诺言中有所收获。 您可以将promise的输出用于您的进一步操作或计划。
  4. 当诺言被破坏时,您想知道为什么诺言的人无法履行他的承诺。 一旦知道了原因并确认诺言被违反,您就可以计划下一步该怎么做或如何处理它。
  5. 在作出承诺时,我们所拥有的只是保证。 我们将无法立即采取行动。 当承诺兑现 (因此我们有预期的结果)或违约 (我们知道原因并因此可以计划应急措施)时,我们可以决定并制定需要做什么。
  6. 您有可能根本没有听到作出承诺的人的回音。 在这种情况下,您希望保留时间阈值。 如果说做出承诺的人在10天内没有回到我身边,我会认为他有一些问题并且不会遵守诺言。 因此,即使对方在15天后回到您身边,也不再重要,因为您已经制定了替代计划。

JavaScript中的承诺

根据经验,对于JavaScript,我总是从MDN Web Docs阅读文档。 在所有资源中,我认为它们提供了最简洁的细节。 我从MDSN Web Docs中阅读了Promises页面,并玩弄了一些代码以了解它。

理解诺言有两个部分。 承诺的创建和承诺的 处理 。 尽管我们的大多数代码通常都能满足其他库创建的Promise的需求,但是完全理解将对我们有一定帮助。 一旦您进入初学者阶段,对“创造承诺”的理解同样重要。

创造承诺

让我们看看创建新承诺的签名。

new Promise( /* executor */ function(resolve, reject) { ... } );

构造函数接受一个称为执行程序的函数。 该executor函数接受两个参数resolvereject ,这两个参数又是函数。 通常使用Promise来简化异步操作或阻塞代码的处理,例如文件操作,API调用,DB调用,IO调用等。这些异步操作的启动在executor函数中进行。 如果异步操作成功,则由promise的创建者调用resolve函数来返回预期结果。 同样,如果发生一些意外错误,则通过调用reject函数将原因继续。

现在我们知道了如何创建承诺。 为了我们的理解,让我们创建一个简单的承诺。

var keepsHisWord;
keepsHisWord = true;
promise1 = new Promise(function(resolve, reject) {
if (keepsHisWord) {
resolve("The man likes to keep his word");
} else {
reject("The man doesnt want to keep his word");
}
});
console.log(promise1);
每一个承诺都有状态和价值

由于此承诺已得到立即解决,因此我们将无法检查承诺的初始状态。 因此,让我们创建一个新的承诺,这将需要一些时间来解决。 最简单的方法是使用setTimeOut函数。

promise2 = new Promise(function(resolve, reject) {
setTimeout(function() {
resolve({
message: "The man likes to keep his word",
code: "aManKeepsHisWord"
});
}, 10 * 1000);
});
console.log(promise2);

上面的代码只是创建了一个承诺,它将在10秒后无条件解决。 因此,我们可以检查诺言的状态,直到兑现为止。

承诺状态,直到解决或被拒绝

一旦十秒过​​去,诺言就解决了。 PromiseStatusPromiseValue都进行了相应更新。 如您所见,我们更新了resolve函数,以便我们可以传递JSON Object而不是简单的字符串。 这只是表明我们也可以在resolve函数中传递其他值。

在10秒后使用JSON对象作为返回值解析的承诺

现在让我们来看一个将被拒绝的诺言。 让我们为此稍微修改诺言1。

keepsHisWord = false;
promise3 = new Promise(function(resolve, reject) {
if (keepsHisWord) {
resolve("The man likes to keep his word");
} else {
reject("The man doesn't want to keep his word");
}
});
console.log(promise3);

由于这将创建未经处理的拒绝,因此Chrome浏览器将显示错误。 您现在可以忽略它。 我们稍后再讲。

拒绝承诺

如我们所见, PromiseStatus可以具有三个不同的值。 pending resolved或已rejected pending创建承诺时, PromiseStatus将处于pending状态,并且在承诺被resolved或被rejected.之前, PromiseValue状态为undefined rejected. 当一个承诺处于已resolved或被rejected状态时,一个承诺被称为已settled. 因此,承诺通常会从待处理状态过渡到已解决状态。

现在我们知道了如何创建承诺,现在我们可以看看如何使用或处理承诺。 这将与理解Promise对象并驾齐驱。

了解承诺对象

根据MDN文档

Promise对象表示异步操作的最终完成(或失败)及其结果值。

Promise对象具有静态方法和prototype methods在静态方法Promise对象可以被独立地应用,而prototype methods上的实例被应用于需要Promise对象。 记住正常的方法和原型都返回Promise ,这使事情的理解变得容易得多。

原型方法

让我们首先从prototype methods开始。共有三种。 重申一下,所有这些方法都可以应用于Promise对象的实例,并且所有这些方法依次返回promise。 以下所有方法为诺言的不同状态转换分配处理程序。 正如我们之前看到的,创建Promise时,它处于pending状态。 当一个承诺是基于他们是否解决一个或多个以下三种方法将运行fulfilledrejected

Promise.prototype.catch(onRejected)

Promise.prototype.then(onFulfilled, onRejected)

Promise.prototype.finally(onFinally)

下面的图像示出了用于流.then.catch方法。 由于它们返回了Promise因此可以再次链接它们,这也显示在图像中。 如果.finally被宣布为一个承诺那么无论什么时候承诺是它将被执行settled其是否满足或拒绝无关。 正如康斯坦丁·鲁达(Konstantin Rouda)所指出的,对“最终”的支持有限,因此请在使用前进行检查。

来自: https : //mdn.mozillademos.org/files/15911/promises.png

这是一个小故事。 您是一个正在上学的孩子,您问妈妈电话。 她说:“我将在本月底购买一部电话。”

让我们看看如果在月底执行了Promise,它将在JavaScript中的外观如何。

var momsPromise = new Promise(function(resolve, reject) {
momsSavings = 20000;
priceOfPhone = 60000;
if (momsSavings > priceOfPhone) {
resolve({
brand: "iphone",
model: "6s"
});
} else {
reject("We donot have enough savings. Let us save some more money.");
}
});
momsPromise.then(function(value) {
console.log("Hurray I got this phone as a gift ", JSON.stringify(value));
});
momsPromise.catch(function(reason) {
console.log("Mom coudn't buy me the phone because ", reason);
});
momsPromise.finally(function() {
console.log(
"Irrespecitve of whether my mom can buy me a phone or not, I still love her"
);
});

输出将是。

妈妈没有兑现诺言。

如果我们将妈妈momsSavings的价值momsSavings为200000,则妈妈将能够为儿子送礼。 在这种情况下,输出将是

妈妈信守诺言

让我们戴上消耗这个图书馆的人的帽子。 我们正在模拟输出和性质,以便我们可以研究如何使用然后有效捕获。

因为.then可以分配两个onFulfilled, onRejected handlers ,而不是单独的写.then.catch我们可以做同样的用.then它看起来会像下面。

momsPromise.then(
function(value) {
console.log("Hurray I got this phone as a gift ", JSON.stringify(value));
},
function(reason) {
console.log("Mom coudn't buy me the phone because ", reason);
}
);

但是为了代码的可读性,我认为最好将它们分开。

为了确保我们可以在常规浏览器或特定于chrome的浏览器中运行所有这些示例,请确保我们的代码示例中没有外部依赖项。 为了更好地理解其他主题,我们创建一个函数,该函数将返回将被随机解决或拒绝的promise,以便我们可以测试各种情况。 为了理解异步函数的概念,让我们在函数中引入随机延迟。 由于我们将需要随机数,因此我们首先创建一个随机函数,该函数将返回x和y之间的随机数。

function getRandomNumber(start = 1, end = 10) {
//works when both start,end are >=1 and end > start
return parseInt(Math.random() * end) % (end-start+1) + start;
}

让我们创建一个函数,该函数将为我们返回承诺。 让我们把我们的功能promiseTRRARNOSG这是一个别名promiseThatResolvesRandomlyAfterRandomNumnberOfSecondsGenerator 。 此函数将创建一个承诺,该承诺将在2到10之间的随机秒数后解析或拒绝。要对拒绝和解析进行随机化,我们将创建1到10之间的随机数。如果生成的随机数大于5,我们将解析答应,否则我们将拒绝它。

function getRandomNumber(start = 1, end = 10) {
//works when both start and end are >=1
return (parseInt(Math.random() * end) % (end - start + 1)) + start;
}
promiseThatResolvesRandomlyAfterRandomNumnberOfSecondsGenerator
var testProimse = promiseTRRARNOSG();
testProimse.then(function(value) {
console.log("Value when promise is resolved : ", value);
});
testProimse.catch(function(reason) {
console.log("Reason when promise is rejected : ", reason);
});
// Let us loop through and create ten different promises using the function to see some variation. Some will be resolved and some will be rejected. 
for (i=1; i<=10; i++) {
let promise = promiseTRRARNOSG();
promise.then(function(value) {
console.log("Value when promise is resolved : ", value);
});
promise.catch(function(reason) {
console.log("Reason when promise is rejected : ", reason);
});
}

刷新浏览器页面并在控制台中运行代码以查看用于resolve方案和reject方案的不同输出。 展望未来,我们将看到我们如何创建多个promise并检查其输出,而无需执行此操作。

静态方法

Promise对象中有四种静态方法。

前两个是助手方法或快捷方式。 它们可以帮助您轻松地创建已解决或已拒绝的承诺。

Promise.reject(reason)

帮助您创建被拒绝的承诺。

var promise3 = Promise.reject("Not interested");
promise3.then(function(value){
console.log("This will not run as it is a resolved promise. The resolved value is ", value);
});
promise3.catch(function(reason){
console.log("This run as it is a rejected promise. The reason is ", reason);
});

Promise.resolve(value)

帮助您创建已解决的承诺。

var promise4 = Promise.resolve(1);
promise4.then(function(value){
console.log("This will run as it is a resovled promise. The resolved value is ", value);
});
promise4.catch(function(reason){
console.log("This will not run as it is a resolved promise", reason);
});

在旁注中,promise可以具有多个处理程序。 因此,您可以将上面的代码更新为

var promise4 = Promise.resolve(1);
promise4.then(function(value){
console.log("This will run as it is a resovled promise. The resolved value is ", value);
});
promise4.then(function(value){
console.log("This will also run as multiple handlers can be added. Printing twice the resolved value which is ", value * 2);
});
promise4.catch(function(reason){
console.log("This will not run as it is a resolved promise", reason);
});

和输出将看起来像。

接下来的两种方法可帮助您处理一组承诺。 当您处理多个promise时,最好先创建一个promise数组,然后对promise集合进行必要的操作。 为了理解这些方法,我们将无法使用我们方便的promiseTRRARNOSG因为它太随机了。 最好有一些确定性的承诺,以便我们能够理解其行为。 让我们创建两个函数。 一种会在n秒后解决,另一种会在n秒后拒绝。

var promiseTRSANSG = (promiseThatResolvesAfterNSecondsGenerator = function(
n = 0
) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve({
resolvedAfterNSeconds: n
});
}, n * 1000);
});
});
var promiseTRJANSG = (promiseThatRejectsAfterNSecondsGenerator = function(
n = 0
) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
reject({
rejectedAfterNSeconds: n
});
}, n * 1000);
});
});

现在让我们使用这些帮助器功能来了解Promise.All

无极

根据MDN文档

Promise.all(iterable)方法返回一个Promise ,当iterable参数中的所有promise已解决或可迭代参数不包含promise时,该Promise会进行解析。 它以第一个承诺被拒绝的理由拒绝。

情况1 :当所有的诺言都实现了。 这是最常用的方案。

console.time("Promise.All");
var promisesArray = [];
promisesArray.push(promiseTRSANSG(1));
promisesArray.push(promiseTRSANSG(4));
promisesArray.push(promiseTRSANSG(2));
var handleAllPromises = Promise.all(promisesArray);
handleAllPromises.then(function(values) {
console.timeEnd("Promise.All");
console.log("All the promises are resolved", values);
});
handleAllPromises.catch(function(reason) {
console.log("One of the promises failed with the following reason", reason);
});
所有的诺言都实现了。

我们通常需要从输出中得出两个重要的观察结果。

第一需要2秒的第三个承诺完成,而需要4秒的第二个承诺完成。 但是,正如您在输出中看到的那样,承诺的顺序将保留在值中。

第二我添加了一个控制台计时器,以找出Promise.All需要多长时间。 如果按顺序执行承诺,则总共应花费1 + 4 + 2 = 7秒。 但是从我们的计时器中我们看到只需要4秒。 这证明了所有诺言都是并行执行的。

情况2:没有承诺时。 我认为这是最不常用的。

console.time("Promise.All");
var promisesArray = [];
promisesArray.push(1);
promisesArray.push(4);
promisesArray.push(2);
var handleAllPromises = Promise.all(promisesArray);
handleAllPromises.then(function(values) {
console.timeEnd("Promise.All");
console.log("All the promises are resolved", values);
});
handleAllPromises.catch(function(reason) {
console.log("One of the promises failed with the following reason", reason);
});

由于数组中没有promise,因此将解决返回的promise。

情况3:以第一个承诺被拒绝的原因拒绝。

console.time("Promise.All");
var promisesArray = [];
promisesArray.push(promiseTRSANSG(1));
promisesArray.push(promiseTRSANSG(5));
promisesArray.push(promiseTRSANSG(3));
promisesArray.push(promiseTRJANSG(2));
promisesArray.push(promiseTRSANSG(4));
var handleAllPromises = Promise.all(promisesArray);
handleAllPromises.then(function(values) {
console.timeEnd("Promise.All");
console.log("All the promises are resolved", values);
});
handleAllPromises.catch(function(reason) {
console.timeEnd("Promise.All");
console.log("One of the promises failed with the following reason ", reason);
});
第一次拒绝后,执行停止

无极种族

根据MDN文档

Promise.race(iterable)方法将返回一个可解决或拒绝的promise,该promise中的一个promise之一会解析或拒绝,并带有该promise的值或原因。

案例1:承诺之一首先解决。

console.time("Promise.race");
var promisesArray = [];
promisesArray.push(promiseTRSANSG(4));
promisesArray.push(promiseTRSANSG(3));
promisesArray.push(promiseTRSANSG(2));
promisesArray.push(promiseTRJANSG(3));
promisesArray.push(promiseTRSANSG(4));
var promisesRace = Promise.race(promisesArray);
promisesRace.then(function(values) {
console.timeEnd("Promise.race");
console.log("The fasted promise resolved", values);
});
promisesRace.catch(function(reason) {
console.timeEnd("Promise.race");
console.log("The fastest promise rejected with the following reason ", reason);
});
最快的分辨率

所有的诺言都是并行进行的。 第三个承诺在2秒内解决。 完成此操作后, Promise.race返回的Promise.race就会解决。

情况2:其中一个诺言首先被拒绝。

console.time("Promise.race");
var promisesArray = [];
promisesArray.push(promiseTRSANSG(4));
promisesArray.push(promiseTRSANSG(6));
promisesArray.push(promiseTRSANSG(5));
promisesArray.push(promiseTRJANSG(3));
promisesArray.push(promiseTRSANSG(4));
var promisesRace = Promise.race(promisesArray);
promisesRace.then(function(values) {
console.timeEnd("Promise.race");
console.log("The fasted promise resolved", values);
});
promisesRace.catch(function(reason) {
console.timeEnd("Promise.race");
console.log("The fastest promise rejected with the following reason ", reason);
});
最快的拒绝

所有的诺言都是并行进行的。 第四个承诺在3秒内被拒绝。 完成此操作后, Promise.race返回的承诺将被拒绝。

我已经编写了所有示例方法,以便可以测试各种场景,并且可以在浏览器本身中运行测试。 这就是在示例中看不到任何API调用,文件操作或数据库调用的原因。 尽管所有这些都是真实的示例,但是您需要付出更多的努力来设置它们并进行测试。 而使用延迟功能可为您提供类似的方案,而无需额外设置。 您可以轻松地使用这些值来查看和签出不同的方案。 您可以结合使用promiseTRJANSGpromiseTRSANSGpromiseTRRARNOSG方法来模拟足够的场景,以全面理解promise。 在相关块之前和之后也使用console.time方法可以帮助我们轻松地确定承诺是并行还是顺序运行。 让我知道您是否还有其他有趣的情况,或者我错过了什么。 如果您希望所有代码示例都放在一个地方,请查看此要点。

蓝鸟具有一些有趣的功能,例如

  1. Promise.prototype.timeout
  2. 承诺
  3. 承诺

我们将在另一篇文章中讨论这些内容。

我还将再写一篇关于我从异步和等待中学习的文章。

在结束之前,我想列出我遵循的所有拇指法则,以使我的头脑保持对诺言的理智。

使用诺言的拇指法则

  1. 每当您使用异步或阻塞代码时,请使用Promise。
  2. resolve映射到thenreject映射到catch所有的实际目的。
  3. 确保写入两根.catch.then对所有承诺的方法。
  4. 如果在两种情况下都需要执行某些操作,请使用.finally
  5. 改变每个诺言我们只有一枪。
  6. 我们可以将多个处理程序添加到一个Promise中。
  7. Promise对象中所有方法的返回类型(无论是静态方法还是原型方法)都是Promise
  8. Promise.all中,所有诺言的顺序都将保持在value变量中,而与首先解决哪个诺言Promise.all

请指出我是否在这里缺少什么,或者是否可以改进。 当我们在MERN堆栈上构建当前产品https://learningpaths.io/时,我开始花更多的时间在Javascript上。 我花了几天的时间在Google上搜索和阅读有关诺言的信息。 跟踪链接和注释真是一团糟。 因此,我们着手构建一个chrome扩展程序,该扩展程序将完全解决此问题并帮助您组织学习路径。 它仍处于Alpha阶段。 我们将与选定的100个人分享它,他们希望尝试一下并向我们提供反馈。 如果您有兴趣,请访问https://learningpaths.io/,并告诉我们您有兴趣获得早期访问权。 如果您认为您的朋友或同事有兴趣,请传播。

如果您喜欢这篇文章并想阅读类似的文章,请别忘了鼓掌。

单击并拖动以拍手不止一次。 限制为50。

理解系列

本文是我的学习系列(称为“ 理解X”)的一部分 。 您可以在此链接中阅读更多内容

了解Javascript

了解Linux

了解React

了解学习

了解加密货币

翻译自: https://hackernoon.com/understanding-promises-in-javascript-13d99df067c1

javascript中对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值