ECMAScript6(15):Promise 对象

} else {

reject(new Error(this.statusText));

}

}

});

return promise;

}

getJSON(‘info.json’).then(

json => id.innerHTML = “

” + json + “
”,

err => id.innerHTML = err

);

如果 resolve 的参数是一个promise:

var p1 = new Promise(function(resolve, reject){

//…

});

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

//…

resolve(p1);

});

上面代码中 p1 的状态传给了 p2,也就是p1运行完成(状态为 resolve 或 reject)后 p2 的回调函数会立刻开始执行:

var p1 = new Promise(function(resolve, reject){

setTimeout(() => reject(new Error(‘failed’)), 3000);

});

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

setTimeout(() => resolve(p1), 1000);

});

p2.then(result => console.log(result));

p2.catch(error => console.log(error));

p1 建立,进入 setTimeout 异步计时器。之后 p2 建立,进入 setTimeout 异步计时器。1s 后 p2 准备执行 resolve, 但是 resolve 的参数是 p1, 此时 p1 还是 Pending 状态,所以 p2 开始等待。又过了 2s, p1 的 reject 执行,变为 rejected 状态,随即 p2 也跟着变成 rejected 状态。

Promise 对象方法

  • then() 方法

then(resolve(value){},reject(value){})方法接受2个函数参数,resolve 在 Promise 状态变为 resolved 时调用,reject 在 Promise 状态变为 rejected 时调用。其中 reject 参数是可选的。和构造函数不同的是,then 方法的 reject 和 resolve 都使用 promise 传出的值作为其唯一的参数。

then() 方法返回一个新的 Promise 实例,注意,不是之前那个。因此可以用链式调用,不断添加”回调”函数。 then 的返回值成了下一个 then 中回调函数的参数:

var p = new Promise(function(resolve, reject){

resolve(“from new Promise”);

}).then(function (value){

console.log(value); //from new Promise 其次输出这个

return “from the first ‘then’”;

}).then(function(value){

console.log(value); //from the first ‘then’ 最后输出这个

return “from the second ‘then’”;

});

console.log§; //Promise{…} 先输出这个

注意,如果 promise 的状态是 resolved 则执行 then参数中的第一个回调函数;如果 promise 的状态是 rejected 则执行 then参数中的第二个回调函数。这个状态是不断传递下来的,这一点和之前的例子类似。

  • catch() 方法:

catch(reject) 方法是 then(null, reject) 的别名,在发生错误的时候执行其参数函数:

new Promise(function(resolve, reject){

resolve(“resolved”);

}).then(function(val){

console.log(val); //resolved

throw new Error(“man-made Error”);

}).catch(function(err){

console.log(err.message); //man-made Error

});

错误会从最初的请求沿着回调函数,一直被传递下来。这一点和传统的错误冒泡类似,无论哪里有错误都可以被捕获到:

new Promise(function(resolve, reject){

reject(new Error(“original Error”));

}).then(function(val){

console.log(val); //不执行

throw new Error(“man-made Error”);

}).catch(function(err){

console.log(err.message); //original Error

});

当然也可以在半路截住错误:

new Promise(function(resolve, reject){

reject(new Error(“original Error”));

}).then(function(val){

console.log(val); //不执行

throw new Error(“man-made Error”);

}, function(err){

console.log(Uncaught Error: ${err.message}); //Uncaught Error: original Error

}).catch(function(err){

console.log(err.message); //不执行

});

这里需要注意以下几点:

  1. reject 和 throw 一样可以抛出错误。

  2. 在 Promise 状态变为 resolved 或 rejected 之后抛出的错误会被忽略。

  3. 建议总是使用 catch() 方法,而不要在 then() 方法中定义 reject 函数。

  4. 如果一个 promise 既没有 catch方法,也没有可以捕获到错误的 then 方法,那么这个错误就消失了。它不会到 promise 外面来。

  5. try…catch… 只能捕获同步代码的错误,不能捕获异步代码的错误(这个是 ES5 就有的)。

  6. catch() 方法可以继续抛出错误,就像 try…catch 中的 catch 一样可以抛出错误。

这里需要说明的是第4条:错误不会到 Promise 外面是 ES6 规范的说法。具体理解(浏览器环境):控制台依旧会报错,但是不影响 promise 语句之后续代码执行。此外,promise 语句内的异步语句(如事件,定时器等等)抛出的错误,不属于 promise 内部,发生错误会传播出去:

var p = new Promise(function(resolve, reject){

resolve(“ok”);

setTimeout(function(){throw new Error(“setTimeout error”)},0);

});

p.then(function(val){console.log(val);}); //ok

//Uncaught Error: setTimeout error

其次,就以上前两个注意事项举一例说明:

new Promise(function(resolve, reject){

resolve(“resolved”);

throw “original Error”; //被忽略

}).then(function(val){

console.log(val); //resolved

throw (new Error(“man-made Error”));

}).catch(function(err){

console.log(err.message); //man-made Error

});

catch 方法的返回值还是一个新的 promise 对象,可以继续调用 then 等其他方法:

new Promise(function(resolve, reject){

reject(new Error(“reject”));

}).catch(function(err){

console.log(“1st catch”); //被跳过

return “continue”;

}).then(function(val){

console.log(val); //continue

});

如果 catch之前没有错误,该 catch 会被跳过。这意味着,catch 不能捕获在其后面的语句中出现的错误:

new Promise(function(resolve, reject){

resolve(“resolved”);

}).catch(function(err){

console.log(“1st catch”); //被跳过

}).then(function(val){

console.log(val); //resolved

throw (new Error());

}).catch(function(err){

console.log(“2nd catch”); //2nd catch

});

  • finally() 方法

finally() 接受一个回调函数(无参数)为参数,和 try…catch…finally 中的 finally 类似,不论 promise 是什么状态,该回调函数都一定会运行。可以用它关闭文件,或者关闭服务器等:

server.listen(0).then(function(){

//do sth.

}).finally(server.stop);

finally() 内部实现如下:

Promise.prototype.finally = function(callback){

return this.then(

value => {Promise.resolve(callback()).then(() => value)},

error => {Promise.resolve(callback()).then(() => {throw error})}

);

};

  • done() 方法

done() 方法用在 promise 处理语句的末端,用来处理可能未捕获的错误,并抛向全局。如果其带有参数,可以等效为 done() 之前多了一个 then():

p.done(fun1, fun2);

//相当于

p.then(fun1,fun2).done();

done() 内部实现如下:

Promise.prototype.done = function(onResolve, onRejected){

this.then(onResolve, onRejected).catch(function(err){

setTimeout(() => {throw err}, 0);

});

};

Promise 静态方法

  • Promise.all()

将多个 promise 对象合并成一个新的 promise 实例。其接受一个装仅有 promise 对象的可遍历结构为参数,如果不是 promise 对象,系统会调用 Promise.resolve() 进行类型转换。

promise.all() 方法得到的新的 promise 对象状态由构成它的所有 promise 对象决定,具体分为2种情况:

  1. 当所有构成它的 promise 对象的状态都变成 resolved,这个新的对象状态才变为 resolved。此时构成它所有的 Promise 的返回值构成一个数组作为新的 promise 对象的回调函数参数;

  2. 当所有构成它的 promise 对象的状态有一个变成 rejected,这个新的对象状态就变为 rejected。此时第一个被 reject 的 Promise 的返回值作为新的 promise 对象的回调函数参数;

//伪代码, 由于没有正确的 url

var getJSON = function(url){

var promise = new Promise(function(resolve, reject){

var client = new XMLHttpRequest();

client.open(“GET”, url);

client.onreadystatechange = handler;

client.response = “json”;

client.setRequestHeader(“Accept”, “application/json”);

client.send();

function handler(){

if(client.readyState !== 4) return;

if(this.status === 200){

resolve(client.response);

} else {

reject(new Error(this.statusText));

}

}

});

return promise;

}

var pros = [‘url1’, ‘url2’, ‘url3’].map(url => getJSON(url));

Promise.all(pros).then(function(){

console.log(“all successful”);

}, function(){

console.log(“one rejected”); //one rejected, 由于没有正确的 url

});

  • Promise.race()

将多个 promise 对象合并成一个新的 promise 实例。其接受一个装仅有 promise 对象的可遍历结构为参数,如果不是 promise 对象,系统会调用 Promise.resolve() 进行类型转换。

和 promise.all() 不同的是 Promise.race() 方法得到的新的 promise 对象状态由构成它的 promise 对象中最先改变状态的那一个决定。

//伪代码, 由于没有正确的 url

var getJSON = function(url){

var promise = new Promise(function(resolve, reject){

var client = new XMLHttpRequest();

client.open(“GET”, url);

client.onreadystatechange = handler;

client.response = “json”;

client.setRequestHeader(“Accept”, “application/json”);

client.send();

function handler(){

if(client.readyState !== 4) return;

if(this.status === 200){

resolve(client.response);

} else {

reject(new Error(this.statusText));

}

}

});

return promise;

}

//如果5s不能获得数据就报错

var p = Promise.race([

getJSON(“url”),

最后

推荐一些系统学习的途径和方法。

路线图

每个Web开发人员必备,很权威很齐全的Web开发文档。作为学习辞典使用,可以查询到每个概念、方法、属性的详细解释,注意使用英文关键字搜索。里面的一些 HTML,CSS,HTTP 技术教程也相当不错。

HTML 和 CSS:

html5知识

css基础知识

  • 17
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值