参考
https://pouchdb.com/2015/05/1...
https://developer.mozilla.org...
http://es6.ruanyifeng.com/#do...

Promises

是一种编写异步代码的方法。

Promise 对象

用于表示一个异步操作的最终状态(完成或失败),以及该异步操作的结果值。

Promise 使用

Promise适用于这样的场景,后面的操作必须根据前面的操作的结果做出相应的反应。 那么后面的操作必须等前面的操作完成并且获得前面操作的结果。假设我们现在有三个操作doSomethingFirst,doSomethingSecond 和finalHandler。doSomethingSecond 需要根据 doSomethingFirst 的结果做出反应finalHandler 需要根据 doSomethingSecond 的结果做出反应流程如下://resOfDoSomethingFirst 是 DoSomethingFirst的结果  doSomethingFirst|-----------------|                  doSomethingSecond(resOfDoSomethingFirst)                  |------------------|                                     finalHandler(doSomethingSecond的结果)                                     |------------------|实现这个场景需要解决以下两个问题:    后面的操作 如何知道 前面的操作 完成了    后面的操作 如何知道 前面的操作 的执行结果是什么//包装第一个操作在 doSomethingFirst 中const doSomethingFirst = new Promise(function(resolve, reject) {  // ... some code  if (/*操作成功 */){    resolve(doSomethingFirstValue);     //将doSomethingFirst对象的状态从“pending”变为“resolved”  } else {    reject(doSomethingFirstError);  }});//包装第二个操作在 doSdoSomethingSecond(resOfDoSomethingFirst) {      // ... some code    return somePromise(); //返回一个promise 对象});//整个操作流程如下:doSomethingFirst()    .then(doSdoSomethingSecond)    .then(finalHandler)    .catch(function (err) {      console.log(err);    })    .finally(() => {···});    通过new Promise创建的Promise 实例doSomethingFirst 有以下方法:    Promise.all(iterable)    Promise.race(iterable)    Promise.reject(reason)    Promise.resolve(value)    Promise.prototype.catch(onRejected)    Promise.prototype.then(onFulfilled, onRejected)    Promise.prototype.finally(onFinally)1. doSomethingSecond 如何知道 doSomethingFirst 操作完成了    通过doSomethingFirst状态的变更通知。    一个 Promise有以下几种状态:        pending: 操作未完成。        fulfilled: 操作完成,并且成功。        rejected: 操作完成,但是失败。    resolve()函数:        在异步操作成功时调用        作用是:将Promise对象的状态从 pending 变为 fulfilled,并将异步操作的结果,作为参数传递出去;    reject()函数:        在异步操作失败时调用        作用是:将Promise对象的状态从 pending 变为 rejected, 并将异步操作的错误,作为参数传递出去。    当操作完成时(Promise对象的状态变为fulfilled 或 rejected时),doSomethingFirst 就会通过then()函数调用doSomethingSecond,doSomethingSecond就知道doSomethingFirst已经完成了。2. doSomethingSecond 如何知道 doSomethingFirst 的执行结果是什么    doSomethingFirst通过给then()函数调用doSomethingSecond(resOfDoSomethingFirst)并把执行结果resOfDoSomethingFirst作为参数传递给doSomethingSecond

Promise.prototype.then(onFulfilled, onRejected)

用于为 Promise 实例添加状态改变时的回调函数返回值:一个新的 Promise,所可以采用链式写法,then()函数后面再调用then()函数参数:    onFulfilled         是一个函数,有一个参数,用来记录变成fulfilled状态返回的结果        当doSomethingFirst这个Promise的状态变成fulfilled 时,onFulfilled作为回调函数被调用    onRejected        是一个函数,有一个参数,用来记录变成rejected状态返回的原因        当doSomethingFirst这个Promise的状态变成rejected 时,onRejected作为回调函数被调用    在当前的例子里参数onFulfilled就是doSomethingSecond(resOfDoSomethingFirst),resOfDoSomethingFirst 记录了doSomethingFirst 变成fulfilled状态返回的结果。注意事项:    当给then()传入的参数不是函数时,它实际上将其解释为then(null),将使先前的Promise的结果落空        Promise.resolve('foo').then(Promise.resolve('bar')).then(function (result) {          console.log(result); // foo        });                等价于        Promise.resolve('foo').then(null).then(function (result) {            console.log(result);// foo         });            上面的代码并没有按照我们期望的打印"bar", 而是打印"foo"        正确的写法是:        Promise.resolve('foo').then(function () {          return Promise.resolve('bar');        }).then(function (result) {          console.log(result); // bar        });给then()传入的参数是函数时,函数的内部我们可以做以下三件事:    1. 返回另外一个promise    2. 返回一个同步值    3. 抛出一个同步错误    示例:返回另外一个promise        doSomethingFirst()            .then(doSdoSomethingSecond)            .then(finalHandler)            //somePromise() 返回promise对象        function doSomethingSecond(resOfDoSomethingFirst) {            return somePromise(); //有return, finalHandler接受到的是resOfDoSomethingSecond            //somePromise();// 没有return, finalHandler接受到的是undefined        }        function finalHandler(resOfDoSomethingSecond) {            // handle resOfDoSomethingSecond        }    示例:返回同步值 && 抛出一个同步错误        返回同步值实际上是将同步代码转换为Promisey代码的一种很棒的方法。例如,假设我们有一个用户的内存缓存。我们可以做到:                    //getUserByName  和 getUserAccountById 都返回promise对象            getUserByName('nolan').then(function (user) {              if (user.isLoggedOut()) { //如果用户注销                throw new Error('user logged out!'); // 抛出一个同步错误              }              if (inMemoryCache[user.id]) {                return inMemoryCache[user.id];       //  返回一个同步值!              }              return getUserAccountById(user.id);    // 返回一个promise!            }).then(function (userAccount) {              // I got a user account!            }).catch(function (err) {              // Boo, I got an error!            });                    如果用户注销,catch()将收到一个同步错误;通过callbacks,这个错误会被忽略        如果任何promise被拒绝,catch()将收到一个异步错误。通常情况下,一个promise 依赖于另一个promise ,但当我们需要两个promises的输出。我们该怎么做    getUserByName('nolan').then(function (user) {      return getUserAccountById(user.id);    }).then(function (userAccount) {      // 在这里我们已经获取到了用户账号userAccount,      // 但是我们也需要user对象时该怎么做?    });        解决方案:    function onGetUserAndUserAccount(user, userAccount) {      return doSomething(user, userAccount);    }        function onGetUser(user) {      return getUserAccountById(user.id).then(function (userAccount) {        return onGetUserAndUserAccount(user, userAccount);      });    }        getUserByName('nolan')      .then(onGetUser)      .then(function () {      // at this point, doSomething() is done, and we are back to indentation 0    });

Promise.prototype.catch(onRejected)

用于指定发生错误时的回调函数。catch 可以捕获返回值:返回一个Promise,处理状态变为rejected的情况参数:    onRejected        是一个函数,有一个参数,用来记录变成rejected状态返回的原因。        当promise 状态变为rejected时被调用。注意事项:catch(rejectHandler)     等同于.then(null, rejectHandler)或.then(undefined, rejectHandler)但是 then(resolveHandler).catch(rejectHandler) 和then(resolveHandler, rejectHandler)不是完全相同的。区别在于:当使用then(resolveHandler, rejectHandler)格式时,如果resolveHandler本身抛出了错误,那么rejecthandler实际上不会捕获错误。所以更建议使用catch 而不是then的第二个参数。示例:    var p1 = new Promise((resolve, reject) => {        resolve('one');    });        // catch函数中可以捕捉到resolveHandler 中的error并打印    p1.then(function () {        throw new Error('oh noes');    }).catch(function (err) {        console.log('err=', err); // Error: oh noes    });        // reject函数不能捕捉到resolveHandler中的error    p1.then(function () {        throw new Error('oh noes');    }, function (err) {        console.log('err=', err);     });

Promise.prototype.finally(onFinally)

用于指定不管 Promise 对象最后状态如何,都会执行的操作finally本质上是then方法的特例promise.finally(() => {  // 语句});// 等同于promise.then(  result => {    // 语句    return result;  },  error => {    // 语句    throw error;  });返回值:返回一个Promise,这个Promise对象设置了 finally 回调函数参数:Promise 结束后调用的函数,onFinally 这个函数不接收任何参数,它仅用于无论最终结果如何都要执行的情况。所以finally方法里面的操作,不应依赖于 Promise 的执行结果。示例:    promise    .then(result => {···})    .catch(error => {···})    .finally(() => {···});

Promise.resolve(value)

用于将现有对象转为 Promise 对象    new Promise(function (resolve, reject) {      resolve(someSynchronousValue);    }).then(/* ... */);    等价于    Promise.resolve(someSynchronousValue).then(/* ... */);返回值:返回一个Promise 对象,这个Promise对象是被给定的值解析过的。参数:    value        将被Promise对象解析的参数        参数类型:            Promise对象            具有then方法的对象            没有then方法的对象            不带有任何参数示例1:参数是一个Promise对象    Promise.resolve将不做任何修改、原封不动地返回这个Promise对象    var p = Promise.resolve([1,2,3]);    console.log("p=", p); //"p=" [object Promise]    console.log('p type= ', typeof(p)); // "p type= " "object"    p.then(function(v) {      console.log("v=",v); //"v=" Array [1, 2, 3]      console.log("v type=",typeof(v)); //"v type=" "object"    });        var p2 =  Promise.resolve(p);    console.log("p2=", p2); //"p2=" [object Promise]    console.log('p2 type= ', typeof(p2)); //"p2 type= " "object"    p2.then(function(v) {      console.log("p2 v=",v); //"p2 v=" Array [1, 2, 3]      console.log("p2 v type=",typeof(v)); //"p2 v type=" "object"    });    p2 == p示例2:参数是一个具有then方法的对象    返回的promise会采用这个thenable的对象的最终状态。    let thenable = {      then: function(resolve, reject) {        resolve(42);      }    };        let p = Promise.resolve(thenable);    p.then(function(value) {      console.log(value);  // 42    });    Promise.resolve方法会将thenable对象转为 Promise 对象,然后就立即执行thenable对象的then方法,thenable对象的then方法执行后,对象p的状态就变为resolved,从而立即执行最后那个then方法指定的回调函数,输出 42示例3:参数是一个没有then方法的对象    var p = Promise.resolve([1,2,3]);    console.log("p=", p); //"p=" [object Promise]    console.log('p type= ', typeof(p)); // "p type= " "object"    p.then(function(v) {      console.log("v=",v); //"v=" Array [1, 2, 3]      console.log("v type=",typeof(v)); //"v type=" "object"    });        var p = Promise.resolve(123);    console.log("p=", p); //"p=" [object Promise]    console.log('p type= ', typeof(p)); // "p type= " "object"    p.then(function(v) {      console.log("v=",v); //"v=" 123      console.log("v type=",typeof(v)); //"v type=" "number"    });        var p = Promise.resolve("123");    console.log("p=", p); //"p=" [object Promise]    console.log('p type= ', typeof(p)); // "p type= " "object"    p.then(function(v) {      console.log("v=",v); //"v=" "123"      console.log("v type=",typeof(v)); //"v type=" "string"    });示例4:不带有任何参数    var p = Promise.resolve();    console.log("p=", p); //"p=" [object Promise]    console.log('p type= ', typeof(p)); // "p type= " "object"    p.then(function(v) {      console.log("v=",v); //"v=" undefined      console.log("v type=",typeof(v)); //"v type=" "undefined"    });注意事项:    立即resolve()的 Promise 对象,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事件循环”的开始时        //在下一轮“事件循环”开始时执行        setTimeout(function () {           console.log('three');        }, 0);        //在本轮“事件循环”结束时执行        Promise.resolve().then(function () {          console.log('two');        });        //立即执行        console.log('one');    结果:        "one"        "two"        "three"                    

Promise.reject(reason)

返回值:返回一个Promise 对象,这个Promise 对象 带有状态是rejected的原因参数:    reason        表示Promise被拒绝的原因    new Promise(function (resolve, reject) {      reject(someSynchronousReson);    }).then(null,function(reason){       //...    });等价于    Promise.reject(someSynchronousReson)    .then(null, function(reason) {      //...    });    示例:    new Promise(function (resolve, reject) {      reject("reject reason");    }).then(null,function(reason){            console.log(reason);//"reject reason"    });        Promise.reject("reject reason").then(null, function(reason) {      console.log(reason); // "reject reason"    });        Promise.reject(new Error("reject reason")).then(null, function(error) {      console.log(error); // Error: reject reason    });注意事项:与Promise.resolve不同的是Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。    const thenable = {      then(resolve, reject) {        reject('出错了');      }    };        Promise.reject(thenable)    .catch(e => { //e不是reject抛出的“出错了”这个字符串,而是thenable对象。      console.log(e === thenable) // true    })

Promise.all(iterable)

用于将多个 Promise 实例,包装成一个新的 Promise 实例返回值:返回一个新的promise对象,iterable中所有的promise都变成resolved状态时返回的 promise才会变为resolved状态; iterable中有一个promise变成rejected状态,promise就会变为rejected状态。参数:    iterable    一个可迭代对象,eg Array 或 String示例: iterable中所有的promise都变成resolved状态时返回的 promise才会变为resolved状态    var p1 = new Promise((resolve, reject) => {       setTimeout(resolve, 1000, 'one');     });     var p2 = new Promise((resolve, reject) => {       setTimeout(resolve, 2000, 'two');     });    var p3 = new Promise((resolve, reject) => {      setTimeout(resolve, 3000, 'three');    });    const p = Promise.all([p1, p2, p3]).then(values => {       console.log(values); //["one", "two", "three"]    }).catch(reason => {      console.log(reason); //没执行    });    流程:p创建时为pending状态,当p1, p2, p3的状态都变成resolved时触发p变成resolved状态。    p1    1s    |----------|resolved                          p2    2s     |--------------------|resolved    p3    3s     |------------------------------|resolved                                   p resolved                                   示例:iterable中有一个promise变成rejected状态,promise就会变为rejected状态    var p1 = new Promise((resolve, reject) => {       setTimeout(resolve, 1000, 'one');     });     var p2 = new Promise((resolve, reject) => {       setTimeout(resolve, 2000, 'two');     });    var p3 = new Promise((resolve, reject) => {      reject('reject');    });    const p = Promise.all([p1, p2, p3]).then(values => {       console.log(values); //没执行    }).catch(reason => {      console.log(reason); //"reject"    });        流程:p创建时为pending状态,p3先执行完,p3的状态变成rejected时触发p变成rejected状态。    p1    1s    |----------|resolved                          p2    2s     |--------------------|resolved    p3    |-|rejected      p rejected      示例:如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法    var p1 = new Promise((resolve, reject) => {           setTimeout(resolve, 1000, 'one');         });         var p2 = new Promise((resolve, reject) => {           setTimeout(resolve, 2000, 'two');         });        var p3 = new Promise((resolve, reject) => {          reject('reject');        }).catch(reason => {          console.log(reason); //reject        });        const p = Promise.all([p1, p2, p3]).then(values => {           console.log(values); // ["one", "two", undefined]        }).catch(reason => {          console.log(reason); //没执行        });        流程:p创建时为pending状态,p3先执行完,p3的状态变成rejected时,调用自己定义的catch函数抛出错误,不会触发p变成rejected状态。当p1 和 p2 也执行完时,触发p变成resolved状态    p1    1s    |----------|resolved                          p2    2s     |--------------------|resolved    p3    |-|rejected                           |p resolved示例:如果传入的参数是一个空的可迭代对象,则返回一个resolved状态的 Promise     const p = Promise.all([]).then(values => { //p创建时状态就为resolved      console.log(values); // []    });

Promise.race(iterable)

同样是将多个 Promise 实例,包装成一个新的 Promise 实例返回值:返回一个新的promise对象,一旦iterable中的某个promise变为resolved或rejected状态,返回的 promise就会变为resolved或rejected状态。谁最先执行完就返回谁的状态参数:    iterable    一个可迭代对象,eg Array 或 String示例: 一旦iterable中的某个promise变为resolved状态,返回的 promise就会变为resolved状态。    var p1 = new Promise((resolve, reject) => {       setTimeout(resolve, 1000, 'one');     });     var p2 = new Promise((resolve, reject) => {       setTimeout(resolve, 2000, 'two');     });    var p3 = new Promise((resolve, reject) => {      setTimeout(resolve, 3000, 'three');    });    const p = Promise.race([p1, p2, p3]).then(values => {       console.log(values); //["one", "two", "three"]    }).catch(reason => {      console.log(reason); //没执行    });流程:p创建时为pending状态,p1先执行完,p1的状态都变成resolved时触发p变成resolved状态。p1    1s|----------|resolved           p resolved                      p2    2s |--------------------|resolvedp3    3s |------------------------------|resolved                                                                  示例:一旦iterable中的某个promise变为rejected状态,返回的 promise就会变为rejected状态。var p1 = new Promise((resolve, reject) => {   setTimeout(resolve, 1000, 'one'); }); var p2 = new Promise((resolve, reject) => {   setTimeout(resolve, 2000, 'two'); });var p3 = new Promise((resolve, reject) => {  reject('reject');});const p = Promise.all([p1, p2, p3]).then(values => {   console.log(values); //没执行}).catch(reason => {  console.log(reason); //"reject"});    流程:p创建时为pending状态,p3先执行完,p3的状态变成rejected时触发p变成rejected状态。p1    1s|----------|resolved                      p2    2s |--------------------|resolvedp3|-|rejected  p rejected