ES6

Promise 临阵磨枪

I promise.

Posted by Saniac on August 15, 2016

文中部分代码及文字摘自Promise迷你书

一步步来

var promise = new Promise(function(resolve,reject){
    //处理状态结束后,调用resolve或reject
});

Promise实例方法:


resolve时调用onFilfilled,reject时调用OnRejected.

如果只想指定异常时的处理,可以用then()只指定onRejected,也可以用

```promise.catch(onReject)```

### 静态方法

```javascript
Promise.all();
Promise.resolve();

###一个栗子

function asyncFunction() {
    return new Promise(function(resolve,reject) {
        setTimeout(function () {
            resolve('second');
            console.log('first');
        },1000);
    });
}

asyncFunction().then(function (value) {
    console.log(value);
},function (error) {
    console.log(error);
});

本例中,’first’会在’second’之前输出。

如果使用catch方法,上例可写做:

asyncFunction().then(function (value) {
    console.log(value);
}).catch(function (error) {
    console.log(error);
})

一个容易产生误解的地方,就是 并不是发生程序错误等报错情况会执行catch ,而是在实例化Promises 时,运行到自己指定的reject,则会发生catch中的事件。

比如说,下面是一个利用promise执行ajax请求的栗子,本例中,req.status不为200时产生reject。 而此时,只是说明http请求没有正常响应,整个程序是没有错误的。

function getURL(URL) {
    return new Promise(function (resolve, reject) {
        var req = new XMLHttpRequest();
        req.open('GET', URL, true);
        req.onload = function () {
            if (req.status === 200) {
                resolve(req.responseText);
            } else {
                reject(new Error(req.statusText));
            }
        };
        req.onerror = function () {
            reject(new Error(req.statusText));
        };
        req.send();
    });
}
// 运行示例
var URL = "http://httpbin.org/get";
getURL(URL).then(function onFulfilled(value){
    console.log(value);
}).catch(function onRejected(error){
    console.error(error);
});

thenable

就像函数中的argument是拥有.length属性的类数组一样,thenable是拥有.then方法的类promise对象, 比如$.ajax()

上面提到的静态方法Promise.resolve()就可以把thenable对象转化为 真·Promise.

var promise = Promise.resolve($.ajax({'xxx.xxx'}));
promise.then(function(value) {
  console.log(value);
})

链式调用

function FA() {
  console.log('A');
}
function FB() {
  console.log('B');
}
function error() {
  console.log('error');
}
function FC() {
  console.log('C');
}
//调用
var promise = Promise.resolve();
promise.then(FA).then(FB).catch(error).then(FC);

插播一道关于promise链式调用的笔试题:

Please give a function which takes an array of asynchronous and run the functions in the array, each one running once the previous function has completed.

function asyncOneByOne(arr) {  
     //your code here 
} 
function one(callback) {  
    setTimeout(function(){
        console.log('first');
        callback();  }, 200); } 
function two(callback) {  
    setTimeout(function(){      
        console.log('second');      
        callback();  }, 0); } 
        asyncOneByOne([one, two]) 
        // will print 
        // > first 
        // > second 

那时候我太naive,用了很土鳖的直接一层套一层的回调函数方法:

 function asyncOneByOne(arr) {
                var foo = function(){}
                if(arr.length===1){arr[0](foo)}
                else {
                    var lt = arr[arr.length-2];
                    var lo = arr[arr.length-1];
                    var arr2=arr.slice(0,-1);
                    arr2[arr2.length-1] = function(foo){
                    lt(function(){lo(foo)});
                    }
                    asyncOneByOne(arr2);
                }
            }
            function one(callback) {
                setTimeout(function(){
                    console.log('first');
                    callback();
                }, 200); }
            function two(callback) {
                setTimeout(function(){console.log('second');
                    callback();}, 0); }
            function three(callback) {
                setTimeout(function(){console.log('third');
                    callback();}, 100); }
            asyncOneByOne([one, two ,three , one]);
            //first
            //second
            //third
            //first
            

然后就没有然后了,现在有了promise,腰不疼了,腿不酸了,一口气上六楼。