亲自打造Deferred对象
经过对比之后,决心学习jQuery,自己打造一个Deferred对象.var util = require('./util.js');function Callbacks() {
var list = [], fireIndex = -1, firing, momery,
self = {
add: function () {
if (list) {
if (firing) {
fireIndex = list.length - 1;
}
(function add(args) {
for (var i = 0; i < args.length; i++) {
var value = args[i];
var type = util.type(value);
if (type === 'function') {
list.push(value);
}
else if (type === 'array') {
add(value);
}
}
})(arguments);
if (!firing && momery) {
this.fire.apply(this, momery);
}
}
return this;
},
remove: function () {
for (var i = 0; i < arguments.length; i++) {
var value = arguments[i];
var index = list.indexOf(v)
if (index > -1) {
list.splice(index, 1);
}
if (index <= firingIndex) {
firingIndex--;
}
}
return this;
},
has: function (fn) {
return fn ?list.indexOf(fn) > -1 :list.length > 0;
},
empty: function () {
if (list) {
list = [];
}
return this;
},
fire: function () {
momery = util.slice.call(arguments);
if (!firing) {
fireing = true;
while (++fireIndex < list.length) {
list[fireIndex].apply(this, momery);
}
list = [];
fireIndex = -1;
}
firing = false;
}
}
return self;
}
function Deferred() {
var state = "pending", scalls = Callbacks(), fcalls = Callbacks(), promise = {
state: function () {
return state;
},
always: function () {
var args=util.slice.call(arguments);
this.done(args).fail(args);
return this;
},
then: function (success, fail) {
switch (state) {
case "resolved":
scalls.add(success);
break;
case "rejected":
fcalls.add(fail);
break;
default:
scalls.add(success);
fcalls.add(fail);
break; }
return this;
},
done: function (success) { this.then(success, null);
return this;
},
fail: function (fail) {
this.then(null, fail);
return this;
},
resolve: function () {
if (state === "pending") {
state = "resolved";
scalls.fire.apply(this, arguments);
}
return this;
},
reject: function () {
if (state === "pending") {
state = "rejected";
fcalls.fire.apply(this, arguments);
}
return this;
}
};
return promise;
}
module.exports = {
Deferred: function () {
return Deferred();
},
when: function () {
var deferred = Deferred(), args = util.slice.call(arguments), ramin = len = arguments.length, context;
function update(i) {
return function (value) {
context[i] = arguments.length > 1?util.slice.call(arguments):value;
if (!--ramin) {
deferred.resolve.apply(deferred, context);
}
}
}
if (len > 0) {
context = new Array(len);
for (var i = 0; i < len; i++) {
var def = args[i];
if (def && util.type(def.then) === 'function') {
def.then.call(def, update(i), deferred.reject);
}
else {
update(i)(def);
}
}
}
return deferred;
}
}
测试用例:
var Q = require('./Deferred.js');
var deferred = Q.Deferred();
setTimeout(function () {
deferred.reject(1).then(function (r) { console.log("r4:" + r); }, function (e) { console.log("e4:" + e); });
}, 5000);
deferred.then(function (r) { console.log("r:" + r); }, function (e) { console.log("e:" + e); });
setTimeout(function () {
deferred.reject(2).then(function (r) { console.log("r2:" + r); }, function (e) { console.log("e2:" + e); });
}, 10000);
deferred.then(function (r) { console.log("r3:" + r); }, function (e) { console.log("e3:" + e); });
function A(){
var d = Q.Deferred().done(function (r) { console.log('A'+r); });
setTimeout(function () {
d.resolve('阿');
}, 1000);
return d;
}
function B() {
var d = Q.Deferred().done(function (r) { console.log('B' +r); /*d.resolve('b');*/ });
return d;
}
function C() {
var d = Q.Deferred().done(function (r) { console.log('C' +r); /*d.resolve('c');*/ });
setTimeout(function () {
}, 1000);
return d;
}
Q.when(1, A() , 3).done(function (a,b,c) {
console.log(a);
console.log(b);
console.log(c);
}).fail(function (err) { console.log('err' + err); });
实际应用包装:
var d=require('./lib/deferred');
var util=require('./lib/util');
var mysql = require('mysql');
var settings = require('./config');
exports.process = function (wrappers) {
var con = mysql.createConnection(settings.db);
console.time('process');
con.beginTransaction(function (err) {
if (err) { console.error(err); }
else{
(function (wrappers){
var callee=arguments.callee;
if(util.type(wrappers)=='array'){
function wrapped(wraper){
var deferred= d.Deferred();
con.query(wraper.sql, wraper.data,function(err,rows){
if(err){
deferred.reject(err);
}
else{
deferred.resolve(rows);
}
});
deferred.then(wraper.scall,wraper.fcall);
return deferred;
}
var deferreds=[];
wrappers.forEach(function(wraper,i){
deferreds.push(wrapped(wraper));
});
d.when.apply(null,deferreds).then(function(){
con.commit(function (err) {
if (err) {
console.error(err);
return con.rollback(function () {
con.end(function (err) { if(err){console.error(err);} });
});
}
console.info('process success!');
});
},function(err){
console.error(err);
con.rollback(function () {
con.end(function (err) { if (err) { console.error(err); } });
});
}).always(function () { console.timeEnd('process'); });
}else if(util.type(wrappers)=='object'){
callee([wrappers]);
}
})(wrappers);
}
});
};
亲自打造Deferred对象的更多相关文章
- jquery管理ajax异步-deferred对象
今天跟大家分享一个jquery中的对象-deferred.其实早在jquery1.5.0版本中就已经引入这个对象了.不过可能在实际开发过程中用到的并不多,所以没有太在意. 这里先不说deferred的 ...
- jQuery的deferred对象详解
jQuery的deferred对象详解请猛击下面的链接 http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_ ...
- 【Jquery】$.Deferred 对象
源:http://www.ruanyifeng.com/ deferred三个状态 “已完成”“未完成”“已失败” (1) $.Deferred() 生成一个deferred对象. ...
- jQuery的deferred对象学习
#copy { background-color: lightgreen; padding: 15px; margin: 10px } 一.deferred对象简介 deferred对象是jquery ...
- 【转载】学习资料存档:jQuery的deferred对象详解
我在以前的文章里提到promise和deferred,这两个东西其实是对回调函数的一种写法,javascript的难点之一是回调函数,但是我们要写出优秀的javascript代码又不得不灵活运用回调函 ...
- jQuery的deferred对象使用详解——实现ajax线性请求数据
最近遇到一个ajax请求数据的问题 ,就是想要请求3个不同的接口,然后请求完毕后对数据进行操作,主要问题就是不知道这3个请求誰先返回来,或者是在进行操作的时候不能保证数据都已经回来,首先想到能完成的就 ...
- jQuery的deferred对象详解(转载)
本文转载自: jQuery的deferred对象详解(转载)
- 【转载】jQuery1.5之后的deferred对象详解
原文:http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html 原文作者 ...
- jQuery之Deferred对象详解
deferred对象是jQuery对Promises接口的实现.它是非同步操作的通用接口,可以被看作是一个等待完成的任务,开发者通过一些通过的接口对其进行设置.事实上,它扮演代理人(proxy)的角色 ...
随机推荐
- jupyter notebook安装/代码补全/支持golang 踩坑记
安装(不要用root) 安装anaconda3,然后ln -s bin目录下的jupyter命令到/usr/bin目录下 生成密码备用 敲ipython进入交互终端 In [1]: from note ...
- 浅谈AC自动机
写在前面:从10月23日开始写这篇博文,离NOIP2018只有十多天了.坚持不停课的倔强蒟蒻(我)尽量每天挤时间多搞一搞信竞(然而还要准备期中考试).NOIP争取考一个好成绩吧. 一.简介 AC自动机 ...
- bounds的应用
frame是参考父view的坐标系来设置自己左上角的位置.设置bounds可以修改自己坐标系的原点位置,进而影响到其“子view”的显示位置. 向上滚动scrollview,我们就不断增加scro ...
- [转贴] 软件测试职业发展的 A 面和 B 面
[转贴] 软件测试职业发展的 A 面和 B 面 1.所谓的软件测试技术到底包含什么? 梅子:我先来从传统意义上来谈一下测试技术,主要就是测试分析,测试设计,测试管理,测试执行,自动化测试技术,专项测试 ...
- Python subprocess.Popen() error (No such file or directory)
这个错误很容易引起误解,一般人都会认为是命令执行了,但是命令找不到作为参数对应的文件或者目录.其实还有一层含义,就是这个命令找不到,命令找不到,也会报没有这个文件或者目录的错误. 为什么找不到这个命令 ...
- XgBoost推导与总结
一 .机器学习算法中GBDT和XGBOOST的区别有哪些?(转自知乎https://www.zhihu.com/question/41354392/answer/98658997) xgboost相比 ...
- ionic3 在ios9.0 系统下 会出现ReferenceError:Can't find variable:Intl 错误提示
ionic3 框架开发app 在ios 9.0版本中 ReferenceError:Can't find variable:Intl 错误提示: 在index.html 文件中添加 <scri ...
- 使用AMBER中遇到的一些问题
1.读取蛋白问题 读取无配体pdb文件(loadpdb complex.pdb)时,出现一堆 FATAL: Atom .R<ARG >.A<HD1 > does not hav ...
- Cocos Creator两个类相互引用(调用)
如果两个类相互引用,脚本加载阶段就会出现循环引用,循环引用将导致脚本加载出错:///////////Game.jsvar Item = require("Item");var Ga ...
- 测试Oracle统计信息的导出导入
背景:有时我们会希望可以对Oracle的统计信息整体进行导出导入.比如在数据库迁移前后,希望统计信息保持不变;又比如想对统计信息重新进行收集,但是担心重新收集的结果反而引发性能问题,想先保存当前的统计 ...