Promise 就是处理异步的一个规范方法

a();
b();
alert("a");
如果a() 里面有一个ajax 或者settimeout 
那么alert("a") 会先跑
这就是异步了。
从前我们用一堆callBack函数来解决问题,但是这样写不好看。
promise 的写法美丽多了
依据上面的例子
a().then(b).then(function(){
alert("");
})
这样它会先跑完 a -> b - > alert("");

虽然很多类库都实现了这个功能,甚至游览器也有自带的,而且ecma6好像还会有更好更简单的方法来解决异步的操作 ! 
but ! 人生最鸡巴的就是这个 but! 
当作学习,我还是自己写了一个版本。
这个版本不是 promise a 也不是promise a+ 也不是jQuery Defferd 规范
它是给我自己用的!

个人觉得重点思想就是在 then 的时候返回一个 next promise , 而next promise 记入在上一个promise中,这样就创建了一个promise 连环链

而一个回调函数返回的是promise 或者我们叫thenAble函数,那么我们就把原先的链连接去它的后面就可以了。

     function Promise(fn) {
//如果有放fn进来,那么就调用它,把 pass & fail 做参数传进去
//这样fn 内就可以直接 publish了
if (G.isFunction(fn)) {
var promise = new Promise();
fn.apply(null, [promise.pass.bind(promise), promise.fail.bind(promise)]);
return promise;
}
this.status = "pending";
this.data;
this._nextPromise; //保存下一个的指针,这样才可以连环触发
this._passFn_list = [];
this._failFn_list = [];
this._isAllPassRequest = true; //all or any 用的
//注释
//要改要潜水
//这里只说简单的使用说明吧
/*
//方便的初始化调用法
new Promise(function (pass, fail) {
setTimeout(pass, 100, "zzz"); //第三para是传给方法的参数 = pass(zzz)
}).then(fnPass, fnFail);
//一般调用法
a().then(b).then(c);
function a() {
var promise = new Promise();
setTimeout(function () {
promise.pass("data");
}, 1000);
return promise;
}
//all 和 any 参数是array,它会并发处理
//等待全部处理完验证每个的返回
//unknow 算 true
//(note: 一个promise只保存all or any 1condition default是 all)
//如果要求是 all ,那么回来的全部都必须all 就调用nextPromise.pass else fail
//如果要求是 any ,那么回来的要有至少一个是pass 就调用nextPromise.pass else fail
a().all([b, c], [c, b]).then(b, c);
//.catch, .complete 都是语法糖罢了 //异步loop调用, 这个比较复杂,以后还可以有更多变化
var list = [a, a, a];
var promiseTemp;
for (var i = 0; i < list.length; i++) {
var promise = (promiseTemp == undefined) ? list[i]() : promiseTemp.then(list[i]);
promiseTemp = promise;
}
*/
//简单说明:
/*
两大关键方法
then : 把参数加入fn_list中, 然后new 新的promise, 当前的promise.next 指向新的promise(循环链就开始了) ,然后把新的promise 返回出去
pass/fail : 把fn_list中的方法全部拿出来,然后"并发处理", 检查每一个是不是返回promise, 是的话要记入和跟踪,跟踪其实就是为这个promise加一个then,然后把职责链放进去,交替的感觉。 调用then/all/any的时候如果promise的status不是pending会直接add and 发布data
在并发方法之后 fnList会被清除干净,也就是说一个promise的fnlist的每个方法只会被执行一次
*/
}
Promise.prototype._concatFnList = function (passFn_list, failFn_list) {
//all 和 any 用来concat fn list 的
if (passFn_list != undefined && Array.isArray(passFn_list)) {
this._passFn_list = this._passFn_list.concat(passFn_list);
}
if (failFn_list != undefined && Array.isArray(failFn_list)) {
this._failFn_list = this._failFn_list.concat(failFn_list);
}
}
Promise.prototype._getFinalDataByDataRecordList = function (dataRecord_list) {
//dataRecord_list 是array , 因为大部分时候我们是用一个data罢了,所以这边做一些小过滤
var finalValue;
if (dataRecord_list.length == 1) {
finalValue = dataRecord_list[0].data; //抽取data出来就够了
}
else {
dataRecord_list.orderBy("index");//排好位置(因为all/any是并发,不会按照顺序回来)
finalValue = dataRecord_list.map(function (obj) {
delete obj.index; //洗掉属性 index 排位之后就没用了
return obj;
});
}
return finalValue;
}
Promise.prototype._publish = function (fn_list, that) {
//pass 和 fail 的共用过程
if (fn_list.length > 0) {
var returnPromiseCountRecord = 0; //for all & any 多个并发,同时会有多个promise函数
var dataRecord_list = []; //收集全部函数回来的data {index,data,status}
for (var i = 0, l = fn_list.length; i < l; i++) {
var fn = fn_list[i];
var returnValue = fn.call(that, that.data); //挺关键的一句,这里会确定他返回的是不是promise
(function (i) {
function callBack(data) {
//这里是我们外面的promise链 publish触发的
var result = { index: i, status: this.status, data: data };
dataRecord_list.push(result) //record data
returnPromiseCountRecord--; //之前我们累加计算,这里publish了就要开始累减回去了
//一直到0就准备做ending然后继续外面的职责链了
if (returnPromiseCountRecord == 0) {
var is_allPass = dataRecord_list.every(function (v) {
return (v.status == "unknow" || v.status == "pass");
});
var is_anyPass = dataRecord_list.some(function (v) {
return (v.status == "unknow" || v.status == "pass");
});
var finalValue = that._getFinalDataByDataRecordList(dataRecord_list);
//这里会依据 all or any 做处理 觉得调用下一家的 pass or fail
if ((that._isAllPassRequest && is_allPass) || (!that._isAllPassRequest && is_anyPass)) {
that._nextPromise.pass(finalValue);
}
else {
that._nextPromise.fail(finalValue);
}
}
}
if (returnValue instanceof Promise) {
//是promise的话就要 +count,然后+then给他,把职责链给他,等待他触发
returnPromiseCountRecord++;
var otherPromise = returnValue;
otherPromise.complete(callBack);
}
else {
//不是的话就push data 就好,status : unknow 也算 pass
var result = { index: i, status: "unknow", data: returnValue };
dataRecord_list.push(result);
}
})(i)
}
fn_list.length = 0; //运行完就clear掉
//没有return任何thenable方法
if (returnPromiseCountRecord == 0) {
var finalValue = that._getFinalDataByDataRecordList(dataRecord_list);
that._nextPromise.pass(finalValue); //因为没有pass fail 参考所以一定是pass
}
}
else {
//如果没有效应就去找小一家promise效应
if (that._nextPromise) {
that._nextPromise[that.status](that.data);
}
}
}
Promise.prototype.all = function (passFn_list, failFn_list) {
this._concatFnList(passFn_list, failFn_list);
if (this.status != "pending") this._alreadyPublish();
return this._nextPromise || (this._nextPromise = new Promise());
}
Promise.prototype.any = function (passFn_list, failFn_list) {
this._concatFnList(passFn_list, failFn_list);
this._isAllPassRequest = false;
if (this.status != "pending") this._alreadyPublish();
return this._nextPromise || (this._nextPromise = new Promise());
}
Promise.prototype.then = function (passFn, failFn) {
if (passFn != undefined) this._passFn_list.push(passFn);
if (failFn != undefined) this._failFn_list.push(failFn);
if (this.status != "pending") this._alreadyPublish();
return this._nextPromise || (this._nextPromise = new Promise());
}
Promise.prototype._alreadyPublish = function () {
var that = this;
setTimeout(function () {
that[that.status](that.data);
}, 0);
}
Promise.prototype.pass = function (data) {
var that = this;
this.status = "pass";
this.data = data;
var passFn_list = this._passFn_list;
that._publish(passFn_list, that);
}
Promise.prototype.fail = function (data) {
var that = this;
this.status = "fail";
this.data = data;
var failFn_list = this._failFn_list;
that._publish(failFn_list, that);
}
Promise.prototype.complete = function (completeFn) {
return this.then(completeFn, completeFn);
}
Promise.prototype.catch = function (catchFn) {
return this.then(void 0, catchFn);
}
Promise.prototype.getLastPromise = function () {
var promise = this;
for (var i = 0; i < Number.MAX_VALUE; i++) {
if (promise._nextPromise === undefined) {
return promise;
}
else {
promise = promise._nextPromise;
}
}
}
G.s.Promise = Promise;

Javascript Promise 学习(上)的更多相关文章

  1. Javascript Promise 学习笔记

    1.     定义:Promise是抽象异步处理对象以及对其进行各种操作的组件,它把异步处理对象和异步处理规则采用统一的接口进行规范化. 2.     ES6 Promises 标准中定义的API: ...

  2. Javascript - Promise学习笔记

    最近工作轻松了点,想起了以前总是看到的一个单词promise,于是耐心下来学习了一下.   一:Promise是什么?为什么会有这个东西? 首先说明,Promise是为了解决javascript异步编 ...

  3. Javascript Promise 学习 (中)

    时隔多日,对promise有了多一点点的了解. 最近用angularjs 做开发,所以研究了一下它的 $q 功能不算很强大,算是简化版的 Q.js 参考了一下源码,不过我的等级还差很多... 作为学习 ...

  4. JavaScript之Promise学习笔记

    一直想知道Promise到底是怎么实现的,网上一搜几十篇文章,看的一脸蒙蔽.最后算是找到几个讲的真心很详细明了的.看了一份源码看了很久很久……最后找大佬问了几处看不懂的地方,大佬只看了十几分钟就看懂了 ...

  5. Promise 学习笔记 - 时间支配者

    本文同步自我的个人博客:http://www.52cik.com/2015/11/08/promise.html JavaScript 的 promises 事实标准称为 Promises/A+.ES ...

  6. javascript设计模式学习之十六——状态模式

    一.状态模式的定义 状态模式的关键是区分事务内部和外部的状态,事务内部状态改变往往会带来事务的行为改变. 状态模式中有意思的一点是,一般我们谈到封装,都是优先封装对象的行为,而非对象的状态.但在状态模 ...

  7. javascript设计模式学习之八_发布订阅(观察者)模式

    一.发布订阅模式定义 jQuery中的callbacks,defered,promise本质上就是发布订阅模式的实现.ES6的promise内部实现未开源,不了解具体机制 发布订阅模式又叫做观察者模式 ...

  8. [Javascript] Promise

    Promise 代表着一个异步操作,这个异步操作现在尚未完成,但在将来某刻会被完成. Promise 有三种状态 pending : 初始的状态,尚未知道结果 fulfilled : 代表操作成功 r ...

  9. 大量Javascript/JQuery学习教程电子书合集

    [推荐分享]大量Javascript/JQuery学习教程电子书合集,送给有需要的人   不收藏是你的错^_^. 经证实,均可免费下载. 资源名称 资源大小   15天学会jQuery(完整版).pd ...

随机推荐

  1. SKTransition类

    继承自 NSObject 符合 NSObject(NSObject) 框架  /System/Library/Frameworks/SpriteKit.framework 可用性 可用于iOS 7.0 ...

  2. ButterKnife的使用

    ButterKnife是一个Android View注入的库. 1.开始使用 1.1 配置Eclipse 在使用ButterKnife需要先配置一下Eclipse. 项目右键-Properties-J ...

  3. python network programming tutorial

    关于网络编程以及socket 等一些概念和函数介绍就不再重复了,这里示例性用python 编写客户端和服务器端. 一.最简单的客户端流程: 1. Create a socket 2. Connect ...

  4. unicode下各种类型转换,CString,string,char*,int,char[]

    把最近用到的各种unicode下类型转换总结了一下,今后遇到其他的再补充: 1.string转CString string a=”abc”; CString str=CString(a.c_str() ...

  5. java Serializable和Externalizable序列化反序列化详解--转

    一.什么是序列化? “对象序列化”(Object Serialization)是 Java1.1就开始有的特性. 简单地说,就是可以将一个对象(标志对象的类型)及其状态转换为字节码,保存起来(可以保存 ...

  6. [转] Linux Shell 文本处理工具集锦

    内容目录: find 文件查找 grep 文本搜索 xargs 命令行参数转换 sort 排序 uniq 消除重复行 用tr进行转换 cut 按列切分文本 paste 按列拼接文本 wc 统计行和字符 ...

  7. Java基础知识强化83:System类之gc()方法(垃圾回收)以及和finalize()区别

    1. System概述: System类包含一些有用的类字段和方法.它不能被实例化. 2. gc()方法:垃圾回收器 public static void gc()       调用gc方法暗示着Ja ...

  8. yii [error] [exception.CHttpException.404] exception 'CHttpException' with message 'Unable to resolve the request "favicon.ico".'

    yii使用中,发现runtime文件夹下出现这个错误信息 解决办法:在生成的APP程序根目录下建.htaccess文件(前提是需要开启apache重写,具体如何开,查资料咯) 然后配置如下 <I ...

  9. python基础-软件目录开发规范

    为什么要设计好目录结构? "设计项目目录结构",就和"代码编码风格"一样,属于个人风格问题.对于这种风格上的规范,一直都存在两种态度: 一类同学认为,这种个人风 ...

  10. hdu 2156

    #include <iostream> #include <stdio.h> using namespace std; int main() { int i,n; while( ...