> For the complete documentation index, see [llms.txt](https://xiaohesong.gitbook.io/today-i-learn/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://xiaohesong.gitbook.io/today-i-learn/front-end/es6/understanding-es6/promise.md).

# promise

相信大家对这个是挺熟悉的了吧，毕竟都会用到异步函数，这个其实还好，不打算长篇大论的叙述了，简单的说下。 他有在执行(`pending`)的时候，有个简短的生命周期，在`pending`的时候可以叫做`unsettled`, 当`promise`执行结束之后，会变成`settled`,`settled`主要是有下面两种状态

* `Fulfilled`: `promise`成功完成.
* `Rejected`: `promise`未能完成，失败或者其他情况下产生.

并且`promise`有个内部的属性`[[PromiseState]]`,他的值只有这三种`pending`, `fulfilled`, `rejected`.这个属性是不对外暴露的，导致编程时不能确定他的状态，但是可以通过`then`来确定.

`then`**方法接受两个参数，第一个是成功的回调函数，第二个是失败时候的回调函数**

所有方法根据这个来生成`then()`方法的都被称之为`thenable`.所有的`promise`都是`thenable`的，但并非所有的`thenable`都是`promise`.

```javascript
thenable = {
    then: function(resolve, reject) {
        resolve(42);
    }
};

p1 = Promise.resolve(thenable);
p2 = Promise.reject(thenable)
p1.then(function(value) {
    console.log(value);     // 42
});

p2.then(i => console.log('in work'), (err) => console.log('is error'))
```

下面来看看操作多个`promise`的。`all`,没错，就是他。

`Promise.all()`接受一个参数，这个参数是可迭代的，并且返回的是在迭代中被成功处理的。而且这些返回的值是按照传递的顺序存储的。

```javascript
p1 = new Promise(function(resolve, reject) {
    resolve(42);
});
p2 = new Promise(function(resolve, reject) {
    resolve(43);
});
p3 = new Promise(function(resolve, reject) {
    resolve(44);
});
p4 = Promise.all([p1, p2, p3]);
p4.then(function(value) {
    console.log(Array.isArray(value));  // true
    console.log('here value is', value) // here value is (3) [42, 43, 44]
    console.log(value[0]);              // 42
    console.log(value[1]);              // 43
    console.log(value[2]);              // 44
});
```

**若**`all()`**存在失败的情况就会立即返回，不会等待其他的完成**,看下面例子:

```javascript
p1 = new Promise(function(resolve, reject) {
    resolve(42);
});
p2 = new Promise(function(resolve, reject) {
    reject(43);
});
p3 = new Promise(function(resolve, reject) {
    resolve(44);
});
p4 = Promise.all([p1, p2, p3]);
p4.catch(function(value) {
    console.log(Array.isArray(value))   // false
    console.log(value);                 // 43
});
```

与`all()`相对的就是`race`方法，他传参和`all`差不多，不过返回的机制却是不同。 `race`是当有一个完成就会返回，而不是等待其他的也完成。 **race**只会关心第一个返回`settled`的结果，如果是`Fulfilled`，那么返回的结果就是`Fulfilled`,如果是`rejected`，那么返回的结果就是`rejected`.

```javascript
p1 = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve(42);
    }, 100);
});
p2 = new Promise(function(resolve, reject) {
    reject(43);
});
p3 = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve(44);
    }, 50);
});
p4 = Promise.race([p1, p2, p3]);
p4.catch(function(value) {
    console.log(value);     // 43
});
```

## 继承自`promise`

```javascript
class MyPromise extends Promise {

    // use default constructor

    success(resolve, reject) {
        return this.then(resolve, reject);
    }

    failure(reject) {
        return this.catch(reject);
    }

}

let promise = new MyPromise(function(resolve, reject) {
    resolve(42);
});

promise.success(function(value) {
    console.log(value);             // 42
}).failure(function(value) {
    console.log(value);
});
```

在这里，他继承了`promise`的所有内置方法。但是略有不同，比如静态方法有四个`Promise.resolve(), Promise.reject(), Promise.all(), Promise.race()`，最后两个静态方法和内置方法的行为相同，但是前面两个方法略有不同。

无论传递的值如何，`MyPromise.resolve()`和`MyPromise.reject()`都将返回`MyPromise`的实例，因为这些方法使用`Symbol.species`属性([之前一文有介绍](https://github.com/xiaohesong/til/blob/master/front-end/es6/understanding-es6/class.md#symbolspecies属性))来确定要返回的`promise`的类型。

```javascript
p1 = new Promise(function(resolve, reject) {
    resolve(42);
});

p2 = MyPromise.resolve(p1);
p2.success(function(value) {
    console.log(value);         // 42
});

console.log(p2 instanceof MyPromise);   // true
```

有些人会说`async`，但是他最终是在`ECMAScript 2017` (`ECMAScript 8`)出的。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://xiaohesong.gitbook.io/today-i-learn/front-end/es6/understanding-es6/promise.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
