Promise和Deferred的用法对比
ES6原生提供了Promise对象,高版本的nodejs可以直接使用,服务器端的开发中借住babel工具也可以使用,但是如果直接用到浏览器中,兼容性还是个问题。试下了最新的firefox和chorme浏览器都支持了,为了安全还是老老实实用jquery提供的Deferred对象吧。Promise能实现的功能$.Deferred也能实现。
原生Promise
废话就不多说了,直接上api:
- Promise.resolve()
- Promise.reject()
- Promise.all()
- Promise.then()
- Promise.catch()
- Promise.race() // jQuery.Deferred没找到对应的
jQuery.Deferred
对应的api有:
- deferred.resolve() => Promise.resolve()
- deferred.reject() => Promise.reject()
- jQuery.when() => Promise.all()
- deferred.then() => Promise.then()
- deferred.fail() => Promise.catch()
对比deferred.resolve和Promise.resolve的例子
两者resolve和then的用法都一样
原生Promise
1 2 3 4 5 6 7 8 9 10 11 12
| var wait = function () { return new Promise((resolve, reject) => { var task = () => { resolve('done'); } setTimeout(task, 5000); }); }
wait().then((value) => { console.log(value); });
|
jQuery版
1 2 3 4 5 6 7 8 9 10 11 12
| var wait = function () { return $.Deferred((deferred) => { var task = () => { deferred.resolve('done'); } setTimeout(task, 5000); }).promise(); }
wait().then((value) => { console.log(value); });
|
对比deferred.fail和Promise.catch的例子
两个用法差不多
原生Promise
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var wait = function () { return new Promise((resolve, reject) => { reject('error'); }); }
wait().then((value) => { }).catch ((error) => { console.log(error) });
wait().then((value) => { }, (error) => { console.log(error) });
|
jQuery版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var wait = function () { return $.Deferred((deferred) => { deferred.reject('error'); }).promise(); }
wait().then((value) => { }).fail((error) => { console.log(error); });
wait().then((value) => { }, (error) => { console.log(error) });
|
对比Promise.all和jQuery.when的例子
这两个区别是传入参数和返回值都不同,jQuery.when参数为单个deferred函数jQuery.when(deferred1, deferred2, deferred3);Promise.all参数为promise数组,Promise.all([promise1, promise2, promise3])。
Promise返回结果为数组,$.when返回结果和参数对应。
原生Promise
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var promise1 = new Promise((resolve) => { setTimeout(() => { resolve("promise1"); }, 2000); });
var promise2 = new Promise( (resolve) => { setTimeout(() => { resolve("promise2"); }, 1000); });
Promise.all([promise1, promise2]).then((result) => { console.log(result); });
|
jQuery版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var deferred1 = $.Deferred((deferred) => { setTimeout(() => { deferred.resolve("deferred1"); }, 2000); });
var deferred2 = $.Deferred( (deferred) => { setTimeout(() => { deferred.resolve("deferred2"); }, 1000); });
$.when.(deferred1, deferred2).then((result1, result2) => { console.log(result1, result2); });
|
实际开发中特殊情况填坑
根据在实际开发的经验,参数为[promise1, promise2, promise3]这种方式的更方便,某些情况$.when实现起来很悲剧。思考下面的多文件上传时$.Deferred怎么实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| var files = [1, 2, 3]; var handleUpload = (file) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(file+" file uploaded"); }, 1000); }); }
var promiseArr = Array.prototype.slice.call(files, 0).map((file) => { return handleUpload(file); });
Promise.all(promiseArr).then((allFiles) => { console.log(allFiles); }).catch (function (err) { console.log(err); });
|
用$.Deferred也不麻烦,$.Deferred版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
var files = [1, 2, 3]; var handleUpload = (file) => { return $.Deferred((deferred) => { setTimeout(() => { deferred.resolve(file+" file uploaded"); }, 1000); }).promise(); }
var promiseArr = Array.prototype.slice.call(files, 0).map((file) => { return handleUpload(file); });
$.when.apply($, promiseArr).then(function() { var allFiles = Array.prototype.slice.call(arguments); console.log(allFiles); }).fail (function (err) { console.log(err); });
|
相关链接
jQuery Deferred 文档
阮老师的 jQuery的deferred对象详解