Promise 对象
Promise 对象
  Promise 的含义
    Promise 是异步编程的一种解决方案
    所谓Promise，简单说就是一个容器，里面保存着某个未来才会结束的事件（通常是一个异步操作）的结果
    从语法上说，Promise 是一个对象，从它可以获取异步操作的消息。
    Promise 提供统一的 API，各种异步操作都可以用同样的方法进行处理
    romise对象有以下两个特点
      （1）对象的状态不受外界影响
      （2）一旦状态改变，就不会再变，任何时候都可以得到这个结果
    有了Promise对象，就可以将异步操作以同步操作的流程表达出来，避免了层层嵌套的回调函数
    Promise对象提供统一的接口，使得控制异步操作更加容易
    缺点
      无法取消Promise，一旦新建它就会立即执行，无法中途取消
      如果不设置回调函数，Promise内部抛出的错误，不会反应到外部
      当处于pending状态时，无法得知目前进展到哪一个阶段（刚刚开始还是即将完成）
  基本用法
    Promise对象是一个构造函数，用来生成Promise实例
    Promise构造函数接受一个函数作为参数，该函数的两个参数分别是resolve和reject。它们是两个函数，由 JavaScript 引擎提供，不用自己部署
    resolve函数的作用是，将Promise对象的状态从“未完成”变为“成功”（即从 pending 变为 resolved），在异步操作成功时调用，并将异步操作的结果，作为参数传递出去；
    reject函数的作用是，将Promise对象的状态从“未完成”变为“失败”（即从 pending 变为 rejected），在异步操作失败时调用，并将异步操作报出的错误，作为参数传递出去
    Promise实例生成以后，可以用then方法分别指定resolved状态和rejected状态的回调函数
      promise.then(function(value) {
// success
}, function(error) {
// failure
});
    then方法可以接受两个可选的回调函数作为参数
      第一个回调函数是Promise对象的状态变为resolved时调用
      第二个回调函数是Promise对象的状态变为rejected时调用
    Promise 新建后就会立即执行
    异步加载图片的例子
    用Promise对象实现的 Ajax 操作的例子
    如果调用resolve函数和reject函数时带有参数，那么它们的参数会被传递给回调函数。reject函数的参数通常是Error对象的实例，表示抛出的错误；resolve函数的参数除了正常的值以外，还可能是另一个 Promise 实例
    注意，调用resolve或reject并不会终结 Promise 的参数函数的执行
      new Promise((resolve, reject) => {
resolve(1);
console.log(2);
}).then(r => {
console.log(r);
});
// 2
// 1
    一般来说，调用resolve或reject以后，Promise 的使命就完成了，后继操作应该放到then方法里面，而不应该直接写在resolve或reject的后面。所以，最好在它们前面加上return语句，这样就不会有意外。
  Promise.prototype.then()
    第一个参数是resolved状态的回调函数，第二个参数是rejected状态的回调函数，它们都是可选的
    返回的是一个新的Promise实例（注意，不是原来那个Promise实例）
  Promise.prototype.catch()
    x相当于是.then(null, rejection)或.then(undefined, rejection)的别名，用于指定发生错误时的回调函数
  Promise.prototype.finally()
    ES2018 引入标准
    用于指定不管 Promise 对象最后状态如何，都会执行的操作
    promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
  Promise.all()
    用于将多个 Promise 实例，包装成一个新的 Promise 实例const p = Promise.all([p1, p2, p3]);
    p的状态由p1、p2、p3决定
      （1）只有p1、p2、p3的状态都变成fulfilled，p的状态才会变成fulfilled，此时p1、p2、p3的返回值组成一个数组，传递给p的回调函数
      （2）只要p1、p2、p3之中有一个被rejected，p的状态就变成rejected，此时第一个被reject的实例的返回值，会传递给p的回调函数。
  Promise.race()
    同样是将多个 Promise 实例，包装成一个新的 Promise 实例
  Promise.allSettled()
    该方法由 ES2020 引入
    接受一组 Promise 实例作为参数，包装成一个新的 Promise 实例
    只有等到所有这些参数实例都返回结果，不管是fulfilled还是rejected，包装实例才会结束
  Promise.any()
    ES2021 引入了Promise.any()方法
    该方法接受一组 Promise 实例作为参数，包装成一个新的 Promise 实例返回
    只要参数实例有一个变成fulfilled状态，包装实例就会变成fulfilled状态；如果所有参数实例都变成rejected状态，包装实例就会变成rejected状态。
    Promise.any()跟Promise.race()方法很像，只有一点不同，就是不会因为某个 Promise 变成rejected状态而结束
  Promise.resolve()
    用于将现有对象转为 Promise 对象
      const jsPromise = Promise.resolve($.ajax('/whatever.json'));
    参数分成四种情况
      如果参数是 Promise 实例，那么Promise.resolve将不做任何修改、原封不动地返回这个实例
      参数是一个thenable对象，会将这个对象转为 Promise 对象，然后就立即执行thenable对象的then()方法
      如果参数是一个原始值，或者是一个不具有then()方法的对象，则Promise.resolve()方法返回一个新的 Promise 对象，状态为resolved
      不带参数，直接返回一个resolved状态的 Promise 对象
  Promise.reject()
    返回一个新的 Promise 实例，该实例的状态为rejected
  Promise.try()
    还是一个提案
  function loadImageAsync(url) {
return new Promise(function(resolve, reject) {
const image = new Image();
image.onload = function() {
resolve(image);
};
image.onerror = function() {
reject(new Error('Could not load image at ' + url));
};
image.src = url;
});
}
  const getJSON = function(url) {
const promise = new Promise(function(resolve, reject){
const handler = function() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
const client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();
});
return promise;
};
getJSON("/posts.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('出错了', error);
});
  let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
promise.then(function() {
console.log('resolved.');
});
console.log('Hi!');
// Promise
// Hi!
// resolved
  let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let p1 = Promise.resolve(thenable);
p1.then(function (value) {
console.log(value); // 42
});
  const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});