freeCodeCamp/guide/chinese/javascript/promises/index.md

175 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
title: Promises
localeTitle: 承诺
---
## 承诺
JavaScript是单线程的这意味着两个脚本不能同时运行;他们必须一个接一个地跑。 Promise是一个对象表示异步操作的最终完成或失败及其结果值。
```javascript
var promise = new Promise(function(resolve, reject) {
// do thing, then…
if (/* everything worked */) {
resolve("See, it worked!");
}
else {
reject(Error("It broke"));
}
});
```
## 承诺存在于其中一种状态中
* 待定:初始状态,既未履行也未拒绝。
* 实现:操作成功完成。
* 拒绝:操作失败。
Promise对象用作创建promise时未必知道的值的代理。它允许您将处理程序与异步操作的最终成功值或失败原因相关联。这允许异步方法返回类似于同步方法的值异步方法返回一个承诺在将来的某个时刻提供值而不是立即返回最终值。
## 使用'然后'(承诺链接)
要进行多次异步调用并依次同步它们可以使用promise chaining。这允许在后面的后续回调中使用第一个promise中的值。
```javascript
Promise.resolve('some')
.then(function(string) { // <-- This will happen after the above Promise resolves (returning the value 'some')
return new Promise(function(resolve, reject) {
setTimeout(function() {
string += 'thing';
resolve(string);
}, 1);
});
})
.then(function(string) { // <-- This will happen after the above .then's new Promise resolves
console.log(string); // <-- Logs 'something' to the console
});
```
## 承诺API
Promise类中有4个静态方法
* Promise.resolve
* Promise.reject
* Promise.all
* Promise.race
## 承诺可以链接在一起
编写Promise来解决特定问题时可以将它们链接在一起形成逻辑。
```javascript
var add = function(x, y) {
return new Promise((resolve,reject) => {
var sum = x + y;
if (sum) {
resolve(sum);
}
else {
reject(Error("Could not add the two values!"));
}
});
};
var subtract = function(x, y) {
return new Promise((resolve, reject) => {
var sum = x - y;
if (sum) {
resolve(sum);
}
else {
reject(Error("Could not subtract the two values!"));
}
});
};
// Starting promise chain
add(2,2)
.then((added) => {
// added = 4
return subtract(added, 3);
})
.then((subtracted) => {
// subtracted = 1
return add(subtracted, 5);
})
.then((added) => {
// added = 6
return added * 2;
})
.then((result) => {
// result = 12
console.log("My result is ", result);
})
.catch((err) => {
// If any part of the chain is rejected, print the error message.
console.log(err);
});
```
这对于遵循_功能编程_范例很有用。通过创造 用于操纵数据的函数可以将它们链接在一起以组装最终数据 结果。如果在函数链中的任何一点一个值被_拒绝_链 将跳到最近的`catch()`处理程序。
有关函数编程的更多信息: [函数编程](https://en.wikipedia.org/wiki/Functional_programming)
## 函数发生器
在最近的版本中JavaScript引入了更多本机处理Promises的方法。一种这样的方法是函数发生器。函数发生器是“可暂停”的函数。与Promises一起使用时生成器可以使用起来更容易阅读并显示为“同步”。
```javascript
const myFirstGenerator = function* () {
const one = yield 1;
const two = yield 2;
const three = yield 3;
return 'Finished!';
}
const gen = myFirstGenerator();
```
这是我们的第一个生成器,您可以通过`function*`语法看到它。我们声明的`gen`变量不会运行`myFirstGenerator` ,而是“此生成器可以使用”。
```javascript
console.log(gen.next());
// Returns { value: 1, done: false }
```
当我们运行`gen.next()` ,它将取消暂停生成器并继续运行。由于这是我们第一次调用`gen.next()` ,它将运行`yield 1`并暂停,直到我们再次调用`gen.next()` 。当调用`yield 1` ,它将返回给我们产生的`value`以及生成器是否`done` 。
```javascript
console.log(gen.next());
// Returns { value: 2, done: false }
console.log(gen.next());
// Returns { value: 3, done: false }
console.log(gen.next());
// Returns { value: 'Finished!', done: true }
console.log(gen.next());
// Will throw an error
```
当我们继续调用`gen.next()` ,它将继续进行下一次`yield`并且每次都暂停。一旦没有剩余`yield` ,它将继续运行发电机的其余部分,在这种情况下只返回`'Finished!'` 。如果再次调用`gen.next()` ,它将在生成器完成时抛出错误。
现在,假设这个例子中的每个`yield`都是`Promise` ,代码本身看起来非常同步。
### Promise.alliterable对于对不同源的多个请求非常有用
Promise.alliterable方法返回单个Promise当可迭代参数中的所有promise都已解析或者iterable参数不包含promise时它将解析。它拒绝了第一个承诺拒绝的原因。
```javascript
var promise1 = Promise.resolve(catSource);
var promise2 = Promise.resolve(dogSource);
var promise3 = Promise.resolve(cowSource);
Promise.all([promise1, promise2, promise3]).then(function(values) {
console.log(values);
});
// expected output: Array ["catData", "dogData", "cowData"]
```
### 更多信息
有关承诺的更多信息: [承诺](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)