javascript编写_如何编写JavaScript承诺

javascript编写

什么是诺言? (What is a promise?)

A JavaScript promise is an object that represents the completion or failure of an asynchronous task and its resulting value.¹

JavaScript承诺是代表异步任务完成或失败及其结果值的对象。¹

The end.

结束。

I’m kidding of course. So, what does that definition even mean?

我当然是在开玩笑。 那么,这个定义到底意味着什么?

First of all, many things in JavaScript are objects. You can create an object a few different ways. The most common way is with object literal syntax:

首先,JavaScript中的许多东西都是对象。 您可以通过几种不同的方式创建对象。 最常见的方法是使用对象文字语法:

const myCar = {
   color: 'blue',
   type: 'sedan',
   doors: '4',
};

You could also create a class and instantiate it with the new keyword.

您还可以创建一个class ,并使用new关键字实例化它。

class Car {
   constructor(color, type, doors) {
      this.color = color;
      this.type = type;
      this.doors = doors
   }
}

const myCar = new Car('blue', 'sedan', '4');

console.log(myCar);

console.log(myCar);

A promise is simply an object that we create like the later example. We instantiate it with the new keyword. Instead of the three parameters we passed in to make our car (color, type, and doors), we pass in a function that takes two arguments: resolve and reject.

承诺只是我们创建的对象,就像后面的示例一样。 我们使用new关键字实例化它。 我们传入一个带有两个参数的函数,而不是传入用于制造汽车的三个参数(颜色,类型和门): resolvereject

Ultimately, promises tell us something about the completion of the asynchronous function we returned it from–if it worked or didn’t. We say the function was successful by saying the promise resolved, and unsuccessful by saying the promise rejected.

最终,promise会告诉我们有关异步函数完成情况的信息,无论异步函数是否起作用,我们都会从中返回该函数。 我们说承诺已解决 ,则表示该功能是成功的;如果说承诺被拒绝 ,则此功能未成功

const myPromise = new Promise(function(resolve, reject) {});

console.log(myPromise);

console.log(myPromise);

const myPromise = new Promise(function(resolve, reject) {
   resolve(10);
});

See, not too scary–just an object we created. And, if we expand it a bit:

看到的不是太吓人-只是我们创建的对象。 而且,如果我们将其扩展一点:

In addition, we can pass anything we’d like to into resolve and reject. For example, we could pass an object instead of a string:

此外,我们可以将任何我们想解决的事情传递给解决和拒绝者。 例如,我们可以传递一个对象而不是一个字符串:

return new Promise((resolve, reject) => {
   if(somethingSuccesfulHappened) {
      const successObject = {
         msg: 'Success',
         data,//...some data we got back
      }
      resolve(successObject); 
   } else {
      const errorObject = {
         msg: 'An error occured',
         error, //...some error we got back
      }
      reject(errorObject);
   }
});

Or, as we saw earlier, we don’t have to pass anything:

或者,正如我们前面所看到的,我们不必传递任何内容:

return new Promise((resolve, reject) => {
   if(somethingSuccesfulHappend) {
      resolve()
   } else {
      reject();
   }
});
定义的“异步”部分又如何呢? (What about the “asynchronous” part of the definition?)

JavaScript is single threaded. This means it can only run one thing at a time. If you can imagine a road, you can think of JavaScript as a single lane highway. Certain code (asynchronous code) can slide over to the shoulder to allow other code to pass it. When that asynchronous code is done, it returns to the roadway.

JavaScript是单线程的。 这意味着它一次只能运行一件事。 如果您可以想象一条道路,那么可以将JavaScript视为一条单线高速公路。 某些代码(异步代码)可以滑到肩膀上,以允许其他代码传递它。 完成该异步代码后,它将返回到巷道。

As a side note, we can return a promise from any function. It doesn’t have to be asynchronous. That being said, promises are normally returned in cases where the function they return from is asynchronous. For example, an API that has methods for saving data to a server would be a great candidate to return a promise!

附带说明一下,我们可以从任何函数返回promise。 它不必是异步的。 话虽如此,通常在诺言返回的函数是异步的情况下返回诺言。 例如,具有将数据保存到服务器的方法的API可以很好地返回承诺!

The takeaway:

外卖:

Promises give us a way to wait for our asynchronous code to complete, capture some values from it, and pass those values on to other parts of our program.

承诺为我们提供了一种等待异步代码完成,从中获取一些值并将这些值传递给程序其他部分的方法。

I have an article here that dives deeper into these concepts: Thrown For a Loop: Understanding Loops and Timeouts in JavaScript.

我在这里有一篇文章,深入探讨了这些概念: 抛出循环:了解JavaScript中的循环和超时。

我们如何使用诺言? (How do we use a promise?)

Using a promise is also called consuming a promise. In our example above, our function returns a promise object. This allows us to use method chaining with our function.

使用诺言也称为消耗诺言。 在上面的示例中,我们的函数返回一个Promise对象。 这使我们可以在函数中使用方法链接。

Here is an example of method chaining I bet you’ve seen:

这是我打赌您已经看到的方法链接示例:

const a = 'Some awesome string';
const b = a.toUpperCase().replace('ST', '').toLowerCase();

console.log(b); // some awesome ring

Now, recall our (pretend) promise:

现在,回想一下我们的(假装的)承诺:

const somethingWasSuccesful = true;

function someAsynFunction() {
   return new Promise((resolve, reject){
      if (somethingWasSuccesful) {
         resolve();     
      } else {
         reject()
      }
   });
}

And, consuming our promise by using method chaining:

并且,通过使用方法链接来履行我们的承诺:

someAsyncFunction
   .then(runAFunctionIfItResolved(withTheResolvedValue))
   .catch(orARunAfunctionIfItRejected(withTheRejectedValue));

一个(更多)真实的例子。 (A (more) real example.)

Imagine you have a function that gets users from a database. I’ve written an example function on Codepen that simulates an API you might use. It provides two options for accessing the results. One, you can provide a callback function where you can access the user or any error. Or two, the function returns a promise as a way to access the user or error.

假设您有一个从数据库获取用户的函数。 我在Codepen上编写了一个示例函数,用于模拟您可能使用的API。 它提供了两种访问结果的选项。 一,您可以提供一个回调函数,您可以在其中访问用户或任何错误。 或两个,函数返回一个promise作为访问用户或错误的一种方式。

Traditionally, we would access the results of asynchronous code through the use of callbacks.

传统上,我们将通过使用回调来访问异步代码的结果。

rr someDatabaseThing(maybeAnID, function(err, result)) {
   //...Once we get back the thing from the database...
   if(err) {
      doSomethingWithTheError(error)
   }   else {
      doSomethingWithResults(results);
   }
}

The use of callbacks is ok until they become overly nested. In other words, you have to run more asynchronous code with each new result. This pattern of callbacks within callbacks can lead to something known as “callback hell.”

使用回调是确定的,直到他们变得过于嵌套。 换句话说,您必须为每个新结果运行更多异步代码。 回调中的这种回调模式可能导致称为“回调地狱”的事情。

Promises offer us a more elegant and readable way to see the flow of our program.

Promises为我们提供了一种更优雅,更易读的方式来查看程序的流程。

doSomething()
   .then(doSomethingElse) // and if you wouldn't mind
   .catch(anyErrorsPlease);

写下我们自己的诺言:金发姑娘,三只熊和一台超级计算机 (Writing our own promise: Goldilocks, the Three Bears, and a Supercomputer)

Imagine you found a bowl of soup. You’d like to know the temperature of that soup before you eat it. You're out of thermometers, but luckily, you have access to a supercomputer that tells you the temperature of the bowl of soup. Unfortunately, this supercomputer can take up to 10 seconds to get the results.

想象一下,你发现了一碗汤。 您想在吃汤之前先知道汤的温度。 您没有温度计,但是幸运的是,您可以使用一台超级计算机,该计算机可以告诉您一碗汤的温度。 不幸的是,这台超级计算机最多可能需要10秒钟才能得到结果。

Here are a couple of things to notice.

这里有几件事要注意。

  1. We initiate a global variable called result.

    我们启动一个名为result的全局变量。

  2. We simulate the duration of the network delay with Math.random() and setTimeout().

    我们使用Math.random()setTimeout()模拟网络延迟的持续时间。

  3. We simulate a temperature with Math.random().

    我们使用Math.random()模拟温度。

  4. We keep the delay and temperature values confined within a range by adding some extra “math”. The range for temp is 1 to 300; the range for delay is 1000ms to 10000ms (1s to 10 seconds).

    通过添加一些额外的“数学”,我们将延迟和温度值限制在一个范围内。 temp的范围是1到300。 delay范围是1000ms至10000ms(1s至10秒)。

  5. We log the delay and temperature so we have an idea of how long this function will take and the results we expect to see when it’s done.

    我们记录延迟和温度,以便我们了解此功能将花费多长时间以及完成后希望看到的结果。

Run the function and log the results.

运行该功能并记录结果。

getTemperature(); 
console.log(results); // undefined
温度不确定。 发生了什么? (The temperature is undefined. What happened?)

The function will take a certain amount of time to run. The variable is not set until the delay is over. So while we run the function, setTimeout is asynchronous. The part of the code in setTimeout moves out of the main thread into a waiting area.

该功能需要一定的时间才能运行。 延迟结束后才设置变量。 因此,当我们运行函数时, setTimeout是异步的。 setTimeout中的代码部分移出主线程进入等待区。

I have an article here that dives deeper into this process: Thrown For a Loop: Understanding Loops and Timeouts in JavaScript.

我在这里有一篇文章更深入地介绍了此过程: 抛出循环:了解JavaScript中的循环和超时。

Since the part of our function that sets the variable result moves into a holding area until it is done, our parser is free to move onto the next line. In our case, it’s our console.log(). At this point, result is still undefined since our setTimeout is not over.

由于函数的设置变量result将移入保存区域直至完成,因此解析器可以自由移至下一行。 在我们的例子中,这是我们的console.log() 。 此时, result setTimeout尚未结束, result仍然不确定。

So what else could we try? We could run getTemperature() and then wait 11 seconds (since our max delay is ten seconds) and then console.log the results.

那么我们还能尝试什么呢? 我们可以运行getTemperature()然后等待11秒(因为我们的最大延迟是10秒), 然后 console.log结果。

getTemperature();
   setTimeout(() => {
      console.log(result); 
   }, 11000);
   
// Too Hot | Delay: 3323 | Temperature: 209 deg

This works, but the problem with this technique is, although in our example we know the maximum network delay, in a real-life example it might occasionally take longer than ten seconds. And, even if we could guarantee a maximum delay of ten seconds, if the result is ready sooner, we are wasting time.

这可行,但是此技术的问题是,尽管在我们的示例中我们知道最大网络延迟,但在实际示例中,有时可能会花费十秒以上。 而且,即使我们可以保证最大延迟为十秒,但如果结果早一点准备好了,那也是在浪费时间。

营救承诺 (Promises to the Rescue)

We are going to refactor our getTemperature() function to return a promise. And instead of setting the result, we will reject the promise unless the result is “Just Right,” in which case we will resolve the promise. In either case, we will pass in some values to both resolve and reject.

我们将重构getTemperature()函数以返回承诺。 而且,除非结果是“正当”,否则我们将拒绝承诺,而不是确定结果,在这种情况下,我们将解决承诺。 无论哪种情况,我们都将传递一些值来解决和拒绝。

We can now use the results of our promise we are returning (also know as consuming the promise).

现在,我们可以使用我们返回的诺言的结果(也称为消耗诺言)。

getTemperature()
   .then(result => console.log(result))
   .catch(error => console.log(error));
   
// Reject: Too Cold | Delay: 7880 | Temperature: 43 deg

.then will get called when our promise resolves and will return whatever information we pass into resolve.

.then在我们的诺言解决时将被调用,并将返回我们传递给resolve任何信息。

.catch will get called when our promise rejects and will return whatever information we pass into reject.

当我们的承诺被拒绝时, .catch将被调用,并将返回我们传递给reject任何信息。

Most likely, you’ll consume promises more than you will create them. In either case, they help make our code more elegant, readable, and efficient.

最有可能的是,您消耗的诺言要多于创建的诺言。 无论哪种情况,它们都有助于使我们的代码更优雅,可读性和效率更高。

摘要 (Summary)

  1. Promises are objects that contain information about the completion of some asynchronous code and any resulting values we want to pass in.

    承诺是包含有关一些异步代码的完成以及我们要传递的任何结果值的信息的对象。
  2. To return a promise we use return new Promise((resolve, reject)=> {})

    为了返回承诺,我们使用return new Promise((resolve, reject)=> {})

  3. To consume a promise we use .then to get the information from a promise that has resolved, and .catch to get the information from a promise that has rejected.

    为了消耗,我们使用一个承诺.then摆脱已经解决了承诺的信息,并.catch要收到拒绝承诺的信息。

  4. You’ll probably use (consume) promises more than you’ll write.

    您可能会使用(消费)承诺而不是编写承诺。
参考文献 (References)

1.) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

1.) https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise

翻译自: https://www.freecodecamp.org/news/how-to-write-a-javascript-promise-4ed8d44292b8/

javascript编写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值