晴明的博客园 GitHub      CodePen      CodeWars     

[ES6] promise

 

Promise

new Promise(executor);
new Promise(function(resolve, reject) { ... });

Promise 对象用于延迟(deferred) 计算和异步(asynchronous ) 计算。
一个Promise对象代表着一个还未完成,但预期将来会完成的操作。

Promise 对象是一个返回值的代理,这个返回值在promise对象创建时未必已知。
它允许你为异步操作的成功或失败指定处理方法。
这使得异步方法可以像同步方法那样返回值:异步方法会返回一个包含了原返回值的 promise 对象来替代原返回值。

Promise对象有以下几种状态:

    pending: 初始状态, 非 fulfilled 或 rejected.
    fulfilled: 成功的操作.
    rejected: 失败的操作.

pending状态的promise对象既可转换为带着一个成功值的fulfilled 状态,也可变为带着一个失败信息的 rejected 状态。
当状态发生转换时,promise.then绑定的方法(函数句柄)就会被调用。
(当绑定方法时,如果 promise对象已经处于 fulfilled 或 rejected 状态,那么相应的方法将会被立刻调用, 所以在异步操作的完成情况和它的绑定方法之间不存在竞争条件。)

因为Promise.prototype.then和 Promise.prototype.catch方法返回 promises对象,
 所以它们可以被链式调用—— 一种被称为 composition 的操作。
 
  如果一个promise对象处在fulfilled或rejected状态而不是pending状态,那么它也可以被称为settled状态。
  你可能也会听到一个术语resolved ,它表示promise对象处于settled状态,或者promise对象被锁定在了调用链中。
 


 

#

var promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

 

#

    var getJSON = function(url) {
                var promise = new Promise(function(resolve, reject) {
                    var client = new XMLHttpRequest();
                    client.open("GET", url);
                    client.onreadystatechange = handler;
                    client.responseType = "json";
                    client.setRequestHeader("Accept", "application/json");
                    client.send();

                    function handler() {
                        if (this.readyState !== 4) {
                            return;
                        }
                        if (this.status === 200) {
                            resolve(this.response);
                        } else {
                            reject(new Error(this.statusText));
                        }
                    };
                });
                return promise;
            };
            getJSON("/posts.json").then(function(json) {
                console.log('Contents: ' + json);
            }, function(error) {
                console.error('出错了', error);
            });

#

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8">
        <title></title>
        <style>

        </style>

    </head>

    <body>
        <div id="log"></div>
        <button onclick="testPromise()">click</button>
        <script>
            'use strict';
            var promiseCount = 0;

            function testPromise() {
                var thisPromiseCount = ++promiseCount;
                var log = document.getElementById('log');
                log.insertAdjacentHTML('beforeend', thisPromiseCount + ') Started (<small>Sync code started</small>)<br/>');
                // We make a new promise: we promise a numeric count of this promise, starting from 1 (after waiting 3s)
                var p1 = new Promise(
                    // The resolver function is called with the ability to resolve or
                    // reject the promise
                    function(resolve, reject) {
                        log.insertAdjacentHTML('beforeend', thisPromiseCount + ') Promise started (<small>Async code started</small>)<br/>');
                        // This is only an example to create asynchronism
                        window.setTimeout(function() {
                            // We fulfill the promise !
                            resolve(thisPromiseCount);
                        }, Math.random() * 2000 + 1000);
                    }
                );
                // We define what to do when the promise is resolved/fulfilled with the then() call,
                // and the catch() method defines what to do if the promise is rejected.
                p1.then(
                    // Log the fulfillment value
                    function(val) {
                        log.insertAdjacentHTML('beforeend', val + ') Promise fulfilled (<small>Async code terminated</small>)<br/>');
                    }).catch(
                    // Log the rejection reason
                    function(reason) {
                        console.log('Handle rejected promise (' + reason + ') here.');
                    });
                log.insertAdjacentHTML('beforeend', thisPromiseCount + ') Promise made (<small>Sync code terminated</small>)<br/>');
            }
        </script>
    </body>

</html>

#

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8">
        <title></title>
        <style>

        </style>

    </head>

    <body>
        <div id="log"></div>
        <button onclick="testPromise()">click</button>
        <script>
            'use strict';
            var promiseCount = 0;

            function testPromise() {
                var thisPromiseCount = ++promiseCount;
                var log = document.getElementById('log');
                log.insertAdjacentHTML('beforeend', thisPromiseCount + ') 开始(同步代码开始)<br/>');
                // 我们创建一个新的promise: 然后用'result'字符串解决这个promise (3秒后)
                var p1 = new Promise(function(resolve, reject) {
                    // 解决函数带着解决(resolve)或拒绝(reject)promise的能力被执行
                    log.insertAdjacentHTML('beforeend', thisPromiseCount + ') Promise开始(异步代码开始)<br/>');
                    // 这只是个创建异步解决的示例
                    window.setTimeout(function() {
                        // 我们满足(fullfil)了这个promise
                        resolve(thisPromiseCount)
                    }, Math.random() * 2000 + 1000);
                });
                // 定义当promise被满足时应做什么
                p1.then(function(val) {
                    // 输出一段信息和一个值
                    log.insertAdjacentHTML('beforeend', val + ') Promise被满足了(异步代码结束)<br/>');
                });
                log.insertAdjacentHTML('beforeend', thisPromiseCount + ') 建立了Promise(同步代码结束)<br/><br/>');
            }
        </script>
    </body>

</html>

#XMLHttpRequest

            'use strict';
            // A-> $http function is implemented in order to follow the standard Adapter pattern
            function $http(url) {
                // A small example of object
                var core = {
                    // Method that performs the ajax request
                    ajax: function(method, url, args) {
                        // Creating a promise
                        var promise = new Promise(function(resolve, reject) {
                            // Instantiates the XMLHttpRequest
                            var client = new XMLHttpRequest();
                            var uri = url;
                            if (args && (method === 'POST' || method === 'PUT')) {
                                uri += '?';
                                var argcount = 0;
                                for (var key in args) {
                                    if (args.hasOwnProperty(key)) {
                                        if (argcount++) {
                                            uri += '&';
                                        }
                                        uri += encodeURIComponent(key) + '=' + encodeURIComponent(args[key]);
                                    }
                                }
                            }
                            client.open(method, uri);
                            client.send();
                            client.onload = function() {
                                if (this.status >= 200 && this.status < 300) {
                                    // Performs the function "resolve" when this.status is equal to 2xx
                                    resolve(this.response);
                                } else {
                                    // Performs the function "reject" when this.status is different than 2xx
                                    reject(this.statusText);
                                }
                            };
                            client.onerror = function() {
                                reject(this.statusText);
                            };
                        });
                        // Return the promise
                        return promise;
                    }
                };
                // Adapter pattern
                return {
                    'get': function(args) {
                        return core.ajax('GET', url, args);
                    },
                    'post': function(args) {
                        return core.ajax('POST', url, args);
                    },
                    'put': function(args) {
                        return core.ajax('PUT', url, args);
                    },
                    'delete': function(args) {
                        return core.ajax('DELETE', url, args);
                    }
                };
            };
            // End A
            // B-> Here you define its functions and its payload
            var mdnAPI = 'xx/search.json';
            var payload = {
                'topic': 'js',
                'q': 'Promise'
            };
            var callback = {
                success: function(data) {
                    console.log(1, 'success', JSON.parse(data));
                },
                error: function(data) {
                    console.log(2, 'error', JSON.parse(data));
                }
            };
            // End B
            // Executes the method call 
            $http(mdnAPI)
                .get(payload)
                .then(callback.success)
                .catch(callback.error);
            // Executes the method call but an alternative way (1) to handle Promise Reject case 
            $http(mdnAPI)
                .get(payload)
                .then(callback.success, callback.error);
            // Executes the method call but an alternative way (2) to handle Promise Reject case 
            $http(mdnAPI)
                .get(payload)
                .then(callback.success)
                .then(undefined, callback.error);

 #imgload

    function imgLoad(url) {
            // Create new promise with the Promise() constructor;
            // This has as its argument a function
            // with two parameters, resolve and reject
            return new Promise(function(resolve, reject) {
                // Standard XHR to load an image
                var request = new XMLHttpRequest();
                request.open('GET', url);
                request.responseType = 'blob';
                // When the request loads, check whether it was successful
                request.onload = function() {
                    if (request.status === 200) {
                        // If successful, resolve the promise by passing back the request response
                        resolve(request.response);
                    } else {
                        // If it fails, reject the promise with a error message
                        reject(Error('Image didn\'t load successfully; error code:' + request.statusText));
                    }
                };
                request.onerror = function() {
                    // Also deal with the case when the entire request fails to begin with
                    // This is probably a network error, so reject the promise with an appropriate message
                    reject(Error('There was a network error.'));
                };
                // Send the request
                request.send();
            });
        }
        // Get a reference to the body element, and create a new image object
        var body = document.querySelector('body');
        var myImage = new Image();
        // Call the function with the URL we want to load, but then chain the
        // promise then() method on to the end of it. This contains two callbacks
        imgLoad('myLittleVader.jpg').then(function(response) {
            // The first runs when the promise resolves, with the request.reponse
            // specified within the resolve() method.
            var imageURL = window.URL.createObjectURL(response);
            myImage.src = imageURL;
            body.appendChild(myImage);
            // The second runs when the promise
            // is rejected, and logs the Error specified with the reject() method.
        }, function(Error) {
            console.log(Error);
        });

 

 

 

Promise.prototype.then()

 

p.then(onFulfilled, onRejected);

p.then(function(value) {
   // fulfillment  满足
  }, function(reason) {
  // rejection  拒绝
});


then()方法返回一个Promise。

它有两个参数,分别为Promise在 success 和 failure 情况下的回调函数。

由于 then 和 Promise.prototype.catch() 方法返回promise, 它们可以被链式调用 — 一种称为 composition 的操作.

#使用then方法

    var p1 = new Promise(function (resolve, reject) {
        resolve("成功!");
        // or
        reject ("错误!");
    });

    p1.then(function (value) {
        console.log(value); // 成功!
    }, function (reason) {
        console.log(reason); // 错误!
    });

#链式调用
因为then方法返回一个Promise,可以轻易地链式调用then。

    var p2 = new Promise(function (resolve, reject) {
        resolve(1);
    });

    p2.then(function (value) {
        console.log(value); // 1
        return value + 1;
    }).then(function (value) {
        console.log(value); // 2
    });

    p2.then(function (value) {
        console.log(value); // 1
        return value;
    })

#也可以在别的函数上用Promise的基础API实现链式操作。?

   function fetch_current_data() {
        // fetch() API 返回一个Promise对象。
        // 这个函数暴露了一个类似的API, 除了返回成功值
        // 你还可以做点别的。
        return fetch("current-data.json").then((response) => {
            if (response.headers.get("content-type") != "application/json") {
                throw new TypeError();
            }
            var j = response.json();
            // 可以针对j的做其他操作
            return j; // 返回给fetch_current_data().then()调用者的值
        });
    }

 

 

 

Promise.prototype.catch()

p.catch(onRejected);

p.catch(function(reason) {
   // rejection 拒绝
});

catch() 方法只处理Promise被拒绝的情况,并返回一个Promise。
该方法的行为和调用Promise.prototype.then(undefined, onRejected)相同。

#使用catch方法

   var p1 = new Promise(function (resolve, reject) {
        resolve("成功");
    });

    p1.then(function (value) {
        console.log(value); // "成功!"
        throw "哦,不!";
    }).catch(function (e) {
        console.log(e); // "哦,不!"
    });

#

   var p1 = new Promise(function (resolve, reject) {
        resolve('Success');
    });

    p1.then(function (value) {
        console.log(value); // "Success!"
        throw 'oh, no!';
    }).catch(function (e) {
        console.log(e); // "oh, no!"
    }).then(function () {
        console.log('after a catch the chain is restored');//'after a catch the chain is restored'
    }, function () {
        console.log('Not fired due to the catch');
    });

    // The following behaves the same as above
    p1.then(function (value) {
        console.log(value); // "Success!"
        return Promise.reject('oh, no!');
    }).catch(function (e) {
        console.log(e); // "oh, no!"
    }).then(function () {
        console.log('after a catch the chain is restored');//'after a catch the chain is restored'
    }, function () {
        console.log('Not fired due to the catch');
    });

 

 

Promise.resolve()

Promise.resolve(value);
Promise.resolve(promise);
Promise.resolve(thenable);

Promise.resolve(value)方法返回一个以给定值解析后的Promise对象。
但如果这个值是个thenable(即带有then方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态(指resolved/rejected/pending/settled);
否则以该值为成功状态返回promise对象。

#使用静态方法Promise.resolve

    Promise.resolve("Success").then(function (value) {
        console.log(value); // "Success"
    }, function (value) {
        // 不会被调用
    });

#对一个数组进行resolve

    var p = Promise.resolve([1, 2, 3]);
    p.then(function (v) {
        console.log(v[0]); // 1
    });

#Resolve另一个promise对象

    var original = Promise.resolve(true);
    var cast = Promise.resolve(original);
    cast.then(function (v) {
        console.log(v); // true
    });

#resolve thenable的对象们并抛出错误

    // Resolve一个thennable对象
    var p1 = Promise.resolve({
        then: function (onFulfill, onReject) {
            onFulfill("fulfilled!");
        }
    });
    console.log(p1 instanceof Promise) // true   这是一个Promise对象

    p1.then(function (v) {
        console.log(v); // 输出"fulfilled!"
    }, function (e) {
        // 不会被调用
    });

    // Thenable在callback之前抛出异常
    // Promise rejects
    var thenable = {
        then: function (resolve) {
            throw new TypeError("Throwing");
            resolve("Resolving");
        }
    };

    var p2 = Promise.resolve(thenable);
    p2.then(function (v) {
        // 不会被调用
    }, function (e) {
        console.log(e); // TypeError: Throwing
    });

    // Thenable在callback之后抛出异常
    // Promise resolves
    var thenable = {
        then: function (resolve) {
            resolve("Resolving");
            throw new TypeError("Throwing");
        }
    };

    var p3 = Promise.resolve(thenable);
    p3.then(function (v) {
        console.log(v); // 输出"Resolving"
    }, function (e) {
        // 不会被调用
    });

 

 

Promise.race()

Promise.race(iterable);

Promise.race(iterable)方法返回一个promise,
这个promise在iterable中的任意一个promise被解决或拒绝后,
立刻以相同的解决值被解决或以相同的拒绝原因被拒绝。

#race 函数返回一个Promise,这个Promise根据传入的Promise中的第一个确定状态--不管是接受还是拒绝--的状态而确定状态。

   var p1 = new Promise(function (resolve, reject) {
        setTimeout(resolve, 500, "");
    });
    var p2 = new Promise(function (resolve, reject) {
        setTimeout(resolve, 100, "");
    });

    Promise.race([p1, p2]).then(function (value) {
        console.log(value); // "二"
        // 两个都解决,但p2更快
    });

    var p3 = new Promise(function (resolve, reject) {
        setTimeout(resolve, 100, "");
    });
    var p4 = new Promise(function (resolve, reject) {
        setTimeout(reject, 500, "");
    });

    Promise.race([p3, p4]).then(function (value) {
        console.log(value); // "三"
        // p3更快,所以被解决(resolve)了
    }, function (reason) {
        // 未被执行
    });

    var p5 = new Promise(function (resolve, reject) {
        setTimeout(resolve, 500, "");
    });
    var p6 = new Promise(function (resolve, reject) {
        setTimeout(reject, 100, "");
    });

    Promise.race([p5, p6]).then(function (value) {
        // 未被执行
    }, function (reason) {
        console.log(reason); // "六"
        // p6更快,所以被拒绝(reject了)
    });

 

 

 

Promise.reject()

Promise.reject(reason);

Promise.reject(reason)方法返回一个用reason拒绝的Promise。

#使用静态Promise.reject方法

    Promise.reject("Testing static reject").then(function (reason) {
        // 未被调用
    }, function (reason) {
        console.log(reason); // "Testing static reject"  测试静态拒绝
    });

    Promise.reject(new Error("fail")).then(function (error) {
        // 未被调用
    }, function (error) {
        console.log(error); // Error: fail(…) 堆栈跟踪
    });

 

 

 

 

 

Promise.all()

Promise.all(iterable);

 

all里的方法全部一起执行,并没有顺序之分,一个出错后续不再resolve。


Promise.all(iterable) 方法返回一个promise,该promise会在iterable参数内的所有promise都被解决后被解决,

或者 reject 第一个进入拒绝状态的 promise 的拒绝原因。

 

结果是promise的一组值。

如果传入的可迭代数组中某项不是一个promise,该项会被用Promise.resolve转换为一个promise。

如果任一传入的promise被拒绝了,all Promise立刻带着该promise的拒绝原因进入拒绝(rejected)状态,不再理会其它传入的promise是否被解决。

#

    var promise = Promise.resolve(3);
    Promise.all([true, promise])
            .then(values => {
        console.log(values); // [true, 3]
    });

#Promise.all waits for all fulfillments (or the first rejection).

    var p1 = Promise.resolve(3);
    var p2 = 1337;
    var p3 = new Promise(function (resolve, reject) {
        setTimeout(resolve, 100, "foo");
    });

    Promise.all([p1, p2, p3]).then(function (values) {
        console.log(values); // [3, 1337, "foo"]
    });

#Promise.all fail-fast behaviour

只有有一个reject ,则立马全部进入reject

    var p1 = new Promise(function (resolve, reject) {
        setTimeout(resolve, 1000, "one");
    });
    var p2 = new Promise(function (resolve, reject) {
        setTimeout(resolve, 2000, "two");
    });
    var p3 = new Promise(function (resolve, reject) {
        setTimeout(resolve, 3000, "three");
    });
    var p4 = new Promise(function (resolve, reject) {
        setTimeout(resolve, 4000, "four");
    });
    var p5 = new Promise(function (resolve, reject) {
        reject("reject");
    });

    Promise.all([p1, p2, p3, p4, p5]).then(function (value) {
        console.log(value);
    }, function (reason) {
        console.log(reason)//"reject"
    });

 

posted @ 2016-05-24 09:57  晴明桑  阅读(262)  评论(0编辑  收藏  举报