Promise是抽象异步处理对象以及对其进行各类操做的组件javascript
简言之,使用Promise就是将javascript中异步的方式变换成同步来操做。Promise则是把相似的异步处理对象和处理规则进行规范化, 并按照采用统一的接口来编写,规定方法以外的写法都会报错。简单的示例:java
var promise = getAsyncPromise("fileA.txt"); //处于Pending状态,既不是resolve也不是reject的状态。是promise对象刚被建立后的初始化状态 promise.then(function(result){ // 获取文件内容成功时的处理 成功时状态为onFulfilled }).catch(function(error){ // 获取文件内容失败时的处理 失败时状态为onRejected });
其中,then
和catch
表明函数执行成功和失败的预设操做git
new
关键字var promise = new Promise(function(resolve, reject) { // 异步处理 // 处理结束后、调用resolve 或 reject });
then
promise.then(onFulfilled, onRejected); //onFulfilled函数会在promise对象的revolve状态调用,onRejected为在promise对象reject状态下调用 promise.catch(function());//catch用来代替onRejected抛出错误
如Promise.all()
, Promise.race
,Promise.resolve()
,Promise.reject
等github
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);//传入resolve中的参数会在状态改变的时候,传到then中 } 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); });
Promise.resolve
做用1. Promise.resolve 是 new Promise(func)的快捷方式,如Promise.resolve(42);
与 new Promise(function(resolve){ resolve(42);});
做用2. 将thenable
对象转换为promise对象。thenable
指的是一个具备 .then
方法的对象。json
Promise.reject
Promise.reject(new Error("出错了"))
等价于数组
new Promise(function(resolve,reject){ reject(new Error("出错了")); });
使用promise
Promise.reject(new Error("BOOM!")).catch(function(error){ console.error(error); });
var promise = new Promise(function (resolve){ console.log("inner promise"); // 1 resolve(42); }); promise.then(function(value){ console.log(value); // 3 }); console.log("outer promise"); // 2
输出结果为 1,2,3; 即便resolve当即执行,得出的结果也在下一个时间环里,须要等到下一周期才能执行异步
1.绝对不能对异步回调函数(即便在数据已经就绪)进行同步调用。
2.若是对异步回调函数进行同步调用的话,处理顺序可能会与预期不符,可能带来意料以外的后果。
3.对异步回调函数进行同步调用,还可能致使栈溢出或异常处理错乱等问题。
4.若是想在未来某时刻调用异步回调函数的话,可使用setTimeout
等异步API。函数
对比三段代码:this
第一段:直接判断文件是否加载完成
function onReady(fn) { var readyState = document.readyState; if (readyState === 'interactive' || readyState === 'complete') { fn(); } else { window.addEventListener('DOMContentLoaded', fn); } } onReady(function () { console.log('DOM fully loaded and parsed'); }); console.log('==Starting==');
第二段:使用setTimeout转同步为异步操做
function onReady(fn) { var readyState = document.readyState; if (readyState === 'interactive' || readyState === 'complete') { setTimeout(fn, 0); //使用setTimeout转化同步函数为异步函数 } else { window.addEventListener('DOMContentLoaded', fn); } } onReady(function () { console.log('DOM fully loaded and parsed'); }); console.log('==Starting==');
第三段:使用promise的resolve将统一为异步的方式,减小判断
function onReadyPromise() { return new Promise(function (resolve, reject) { var readyState = document.readyState; if (readyState === 'interactive' || readyState === 'complete') { resolve(); } else { window.addEventListener('DOMContentLoaded', resolve); } }); } onReadyPromise().then(function () { console.log('DOM fully loaded and parsed'); }); console.log('==Starting==');
关于传递参数promise的写法
function doubleUp(value) { return value * 2; } function increment(value) { return value + 1; } function output(value) { console.log(value);// => (1 + 1) * 2 } var promise = Promise.resolve(1);//构造一个返回参数为1的promise对象 promise .then(increment) //此时increment函数中传的vaule值为1 .then(doubleUp) //此时doubleUp函数中传的vaule值为2 .then(output) //此时doubleUp函数中传的vaule值为 4 .catch(function(error){ // promise chain中出现异常的时候会被调用 console.error(error); });
Promise.resolve
和Promise.reject
会对函数中return返回的值进行包装,最终then
返回的结果都是新建立的promise
对象
Promise.all
的使用
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 request = { comment: function getComment() { return getURL('http://azu.github.io/promises-book/json/comment.json').then(JSON.parse); }, people: function getPeople() { return getURL('http://azu.github.io/promises-book/json/people.json').then(JSON.parse); } }; function main() { return Promise.all([request.comment(), request.people()]); } // 运行示例 main().then(function (value) { console.log(value); }).catch(function(error){ console.log(error); });
证实Promise.all
的promise数组是同时开始执行的
// `delay`毫秒后执行resolve function timerPromisefy(delay) { return new Promise(function (resolve) { setTimeout(function () { resolve(delay); }, delay); }); } var startDate = Date.now(); // 全部promise变为resolve后程序退出 Promise.all([ timerPromisefy(1), timerPromisefy(32), timerPromisefy(64), timerPromisefy(128) ]).then(function (values) { console.log(Date.now() - startDate + 'ms'); // 約128ms console.log(values); // [1,32,64,128] });
Promise.race
只要有一个promise对象进入 FulFilled 或者 Rejected 状态的话,就会继续进行后面的处理
// `delay`毫秒后执行resolve function timerPromisefy(delay) { return new Promise(function (resolve) { setTimeout(function () { resolve(delay); }, delay); }); } // 任何一个promise变为resolve或reject 的话程序就中止运行 Promise.race([ timerPromisefy(1), timerPromisefy(32), timerPromisefy(64), timerPromisefy(128) ]).then(function (value) { console.log(value); // => 1 }); //代码第二段 var winnerPromise = new Promise(function (resolve) { setTimeout(function () { console.log('this is winner'); resolve('this is winner'); }, 4); }); var loserPromise = new Promise(function (resolve) { setTimeout(function () { console.log('this is loser'); resolve('this is loser'); }, 1000); }); // 第一个promise变为resolve后程序中止 Promise.race([winnerPromise, loserPromise]).then(function (value) { console.log(value); // => 'this is winner' });
不能进行错误处理的onRejected
function throwError(value) { // 抛出异常 throw new Error(value); } // <1> onRejected不会被调用 function badMain(onRejected) { return Promise.resolve(42).then(throwError, onRejected); } // <2> 有异常发生时onRejected会被调用 function goodMain(onRejected) { return Promise.resolve(42).then(throwError).catch(onRejected); } // 运行示例 badMain(function(){ console.log("BAD"); }); goodMain(function(){ console.log("GOOD"); });
说明:上面代码中<1>中throwError 抛出了异常,onRejected 指定的函数也不会被调用
.then 和 .catch 都会建立并返回一个 新的 promise对象。 Promise实际上每次在方法链中增长一次处理的时候所操做的都不是彻底相同的promise对象。