本文共 11011 字,大约阅读时间需要 36 分钟。
javascript编写
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
关键字实例化它。 我们传入一个带有两个参数的函数,而不是传入用于制造汽车的三个参数(颜色,类型和门): resolve
和reject
。
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(); }});
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:
我在这里有一篇文章,深入探讨了这些概念:
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));
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);
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.
这里有几件事要注意。
We initiate a global variable called result
.
我们启动一个名为result
的全局变量。
We simulate the duration of the network delay with Math.random()
and setTimeout()
.
我们使用Math.random()
和setTimeout()
模拟网络延迟的持续时间。
We simulate a temperature with Math.random()
.
我们使用Math.random()
模拟温度。
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秒)。
Run the function and log the results.
运行该功能并记录结果。
getTemperature(); console.log(results); // undefined
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:
我在这里有一篇文章更深入地介绍了此过程:
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.
这可行,但是此技术的问题是,尽管在我们的示例中我们知道最大网络延迟,但在实际示例中,有时可能会花费十秒以上。 而且,即使我们可以保证最大延迟为十秒,但如果结果早一点准备好了,那也是在浪费时间。
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.
最有可能的是,您消耗的诺言要多于创建的诺言。 无论哪种情况,它们都有助于使我们的代码更优雅,可读性和效率更高。
To return a promise we use return new Promise((resolve, reject)=> {})
为了返回承诺,我们使用return new Promise((resolve, reject)=> {})
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
要收到拒绝承诺的信息。
1.)
1.)
翻译自:
javascript编写
转载地址:http://sywzd.baihongyu.com/