Promise 对象初尝试

《Promise 对象初尝试》

浏览器支撑

《Promise 对象初尝试》
http://caniuse.com/promises/embed/agents=desktop

What is Promise?

Promise是笼统异步处置惩罚对象以及对其举行种种操纵的组件。

说到 javascript 异步操纵,能够想到的是如许:

// 以 jQuery 的 ajax 为例
$.get('/get_url', function(result, status) {
    if(status == 'success') {
        alert('success');
    }
    if(status == 'error') {
        alert('error');
    }
});

关于 ajax 的 get 操纵来讲,是一个异步的历程,经由过程回调函数,在获得返回的时刻才会去实行操纵。

然则试想一下当操纵越来越多,回调内里还要回调的时刻,一层层回调函数是否是让人抓狂,不管在代码可读性照样编写效力来看都是很贫苦的。
看一下我们用 Promise 能够怎样做一个异步的操纵:

// 这个 getData 是我们预先实例好的一个 Promise 对象,怎样处置惩罚这个对象我们这里不议论
var promise = getData('/get_url');![图片形貌][3]
promise.then(function(result) {
    console.log(result);
}).catch(function(error) {
  console.log(error);
});

如许的作风是否是会更好呢,实行一个 promise,然后 then 内里传入回调函数,假如情愿,我们能够在 then 背面再更许多个 then,catch 能够捕获毛病,看起来代码清楚简明多了。
所以,promise的功用是能够将庞杂的异步处置惩罚轻松地举行模式化。

组织函数 Constructor

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

这里的 executor 是我们实例化一个 promise 对象时应当传入的参数,这个参数只一个函数,这个函数吸收两个参数 resolvereject
两个要领:

  • resolve(result) 在 promise 中实行这个要领示意胜利,会在实行以后实行背面的 then 所传入的函数,它吸收到的参数也会被 then 内里的函数吸收到,平常来讲参数为实行效果胜利时刻的数据;

  • reject(error) 在 promise 中实行这个要领示意失利,他平常吸收一个 error 毛病参数,会被背面的 catch 捕获到毛病实行。
    demo:

var testFoo = function() {
    return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve('success');
    }, 2000);
  });
};
testFoo().then(function(result) {
  console.log(result);
}).catch(function(error) {
  console.log(error);
});

在这里我们定义了一个 testFoo 函数,这个函数返回一个Promise的实例化对象,两秒以后会实行resolve('success');,示意胜利,传入一个参数,在两秒以后,我们then内里传入的函数实行了,吸收到了方才谁人参数;然则catch内里的函数并没有实行,由于我们没有在 promise 内里实行谢绝操纵。

假如我们在四秒以后实行 reject 操纵呢:

var testFoo = function() {
    return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve('success');
    }, 2000);
    setTimeout(function() {
      reject('error');
    }, 4000);
  });
};
testFoo().then(function(result) {
  console.log(result);
}).catch(function(error) {
  console.log(error);
});

貌似只涌现resolve的效果,由于一个 promise 没办法做屡次效果操纵。
我们就如许:

var testFoo = function() {
    return new Promise(function(resolve, reject) {
    setTimeout(function() {
      reject('error');
    }, 4000);
  });
};
testFoo().then(function(result) {
  console.log(result);
}).catch(function(error) {
  console.log(error);
});

如今效果如我们所预感了。

PromiseStatus 状况

状况分为三种:

  • fulfilled – Fulfilled 已完成,在 resolve时,挪用 then 的 onFulfilled函数;

  • Rejected – Rejected 谢绝,在reject时,挪用 then 的 onRejected函数,或许 catch 内里的函数;

  • unresolved – Pending 守候,是 promise 初始化的时刻的状况。

promise 的 初始化状况为 unresolved,依据异步效果变成 fulfilled 或许 Rejected,一旦变成个中一个就不可转变,这也是我们之前上面为何实行了 resolve 以后再实行 reject 而没有效果的缘由了。

要领概述

快速要领

  • Promise.resolve() 这个是promise的静态要领

Promise.resolve(10).then(function(value){
    console.log(value);
});

这个要领会让 Promise 马上进入 fulfilled 状况,平常用来测试用。

  • Promise.reject()相应着我们有这个要领

Promise.reject('err').catch(function(err){
    console.log(err);
});

实例要领

  • then(onFulfilled, onRejected)这个要领详细是如许的,传入两个函数,一个处置惩罚fulfilled状况,另一个处置惩罚Rejected状况,平常运用我们只传入第一个函数,第二个放在 catch 来处置惩罚。

  • catch(onRejected)处置惩罚Rejected状况,能够这么明白catch(onRejected)=promise.then(undefined, onRejected)

链式挪用

看看这个 demo:

var testFoo = function() {
    return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve(1);
    }, 2000);
  });
};
testFoo().then(function(result) {
  console.log(result);
  return ++result;
}).then(function(result) {
  console.log(result);
  return ++result;
}).then(function(result) {
  console.log(result);
  return ++result;
}).catch(function(error) {
  console.log(error);
});

// 1
// 2
// 3

能够瞥见效果,这个要领的流程是什么样的呢?
《Promise 对象初尝试》
第一个 then 函数和之前讲的一样,处置惩罚 promise 的 fulfilled,第二个 then 的函数是处置惩罚前一个 then 函数处置惩罚完的效果,他们之间参数通报的门路是前一个 then 函数 return 一个数据,然后后一个 then 函数吸收到这个参数。
假如你情愿,能够再背面加许多许多个 then,他们的流程主如果如许。

假如我们把 catch 提早呢?

var testFoo = function() {
    return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve(1);
    }, 2000);
  });
};
testFoo().then(function(result) {
  console.log(result);
  return ++result;
}).then(function(result) {
  console.log(result);
  return ++result;
}).catch(function(error) {
  console.log(error);
}).then(function(result) {
  console.log(result);
  return ++result;
});

// 1
// 2
// 3

能够看出,效果一样,申明catch只会在发作 reject 的时刻挪用。
那假如在中心的一个 then 中抛出一个非常呢?

var testFoo = function() {
    return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve(1);
    }, 2000);
  });
};
testFoo().then(function(result) {
  console.log(result);
  return ++result;
}).then(function(result) {
  console.log(result);
  throw new Error("throw Error")
  return ++result;
}).then(function(result) {
  console.log(result);
  return ++result;
}).catch(function(error) {
  console.log(error);
});
// 1
// 2
// Error: throw Error

我们在第二个then中抛出一个非常,然后马上被 catch 捕获到,第三个 then 并没有实行。

到这里我们想一下从then的传参和捕获非常来看,新加一个 then 只是注册了一个回调函数那末简朴吗?
不不不,每次挪用then都邑返回一个新创建的promise对象,这就诠释了上面的统统缘由。

并发挪用

试想一个场景,我们实行多个异步操纵(ajax等等),然则我们想在这几个操纵都完成的时刻才去实行一个函数。
假如根据传统的要领来做,代码会很乱很散,症结不文雅。让我们尝试用 promise 。
先看这个 demo

var testFoo = function(time, value) {
    return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve(value);
    }, time * 1000);
  });
};
var tasks = {
  task1: function() {
    return testFoo(1, 2);
  },
  task2: function() {
    return testFoo(1.3, 3);
  },
  task3: function() {
    return testFoo(1.5, 1);
  }
};
var main = function() {
  function recordValue(results, value) {
    results.push(value);
    console.log(value);
    console.log(results);
    return results;
  }
  var pushValue = recordValue.bind(null, []);
  return tasks.task1().then(pushValue).then(tasks.task2).then(pushValue).then(tasks.task3).then(pushValue);
};
main().then(function(value) {
  console.log(value);
});

// [2, 3, 1]

这么完成显著看起来缭乱,迥殊关于 main 函数,可读性也比较差。
那末有无更文雅的要领呢,答案:有!?。

Promise.all

Promise.all 要领吸收一个以 promise 对象为元素的数组,在悉数实行操纵完成后才回挪用then内里的要领,看代码:

var testFoo = function(time, value) {
    return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve(value);
    }, time * 1000);
  });
};
var tasks = {
  task1: function() {
    return testFoo(1, 2);
  },
  task2: function() {
    return testFoo(1.3, 3);
  },
  task3: function() {
    return testFoo(1.5, 1);
  }
};
var main = function() {
  return Promise.all([tasks.task1(), tasks.task2(), tasks.task3()]);
}
main().then(function(result) {
  console.log(result);
});

// [2, 3, 1]

我们吧要实行的 promise 对象作为数组的元素传给 Promise.all()Promise.all().then()内里定义的函数吸收到一个数组,元素是这几个操纵返回的值,递次和 promise 对象放入的递次一样,比方第一个 promise 对象返回的值是2,那末效果的第一个元素就是2。
而且每个promise是同时实行的--并发。
在一切 promise 的状况为 FulFilled 的时刻才会去实行 then 内里的函数。
那末捕获非常呢?
修正一下例子:

var testFoo = function(time, value, err) {
    return new Promise(function(resolve, reject) {
    setTimeout(function() {
      if(err) {
        reject(err);
        return false;
      }
      resolve(value);
    }, time * 1000);
  });
};
var tasks = {
  task1: function() {
    return testFoo(1, 2, 'error');
  },
  task2: function() {
    return testFoo(1.3, 3, 'error1');
  },
  task3: function() {
    return testFoo(1.5, 1);
  }
};
var main = function() {
  return Promise.all([tasks.task1(), tasks.task2(), tasks.task3()]);
}
main().then(function(result) {
  console.log(result);
}).catch(function(err) {
  console.log(err);
});

// [2, 3, 1]

我们让个中2 promise 个抛出非常,看到捕获到了谁人非常,而且是捕获到第一个非常就住手了。
申明 all 的操纵是当一切 promise 状况为 FulFilled 的时刻才会实行 then 的操纵。而一旦有一个 Rejected 就catch这个非常,而且住手。

Promise.race

他和 Promise.all 一样,吸收一个 promise 对象构成的数组,也是并发实行,然则 Promise.race 是只需有一个promise对象进入 FulFilled 或许 Rejected 状况的话,就会继续举行背面的处置惩罚。

var testFoo = function(time, value) {
    return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve(value);
    }, time * 1000);
  });
};
var tasks = {
  task1: function() {
    return testFoo(1, 2);
  },
  task2: function() {
    return testFoo(1.3, 3);
  },
  task3: function() {
    return testFoo(1.5, 1);
  }
};
var main = function() {
  return Promise.race([tasks.task1(), tasks.task2(), tasks.task3()]);
}
main().then(function(result) {
  console.log(result);
});

// 2

能够看到,task1 最早完成,然后就拿到他的值举行 then 操纵。

原文来自我的博客 http://qiutc.me/post/promise-learn-note.html
迎接人人关注~

    原文作者:阿城
    原文地址: https://segmentfault.com/a/1190000004697635
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞