为了解决回调地狱的问题,所以出现了promise的设计思想。

#### promise A+ 规范
[https://promisesaplus.com/](https://promisesaplus.com/)
#### 几点需要强调的。
- promise 必须有一个then方法。
- promise 必须有三个状态。"PENDING" "FULFILLED" "REJECTED" 。状态一旦改变,不可回滚。
- promise 可以链式调用。promise 可以穿透(不写resolve方法或者是一个常量也行)。
- promise 返回一个新的promise。
- 捕获错误机制。找不到就向下找。

#### 手写一个promise的思路。总体就是数组保存所有的then里注册的函数。然后等时机到了一个个执行。

(1) 先有一个类,有then方法。status有三个变量pending,fulfilled,rejected。
(2) 成功的变量value和失败的变量reason,保存成功回调onResolvedCallbacks,保存失败的回调onRejectedCallbacks
(3) 主体是then函数的递归,链式调用所有then返回一个promise。但是为了解决then函数的返回普通值和then穿透的问题。

#### 如何证明promise和x重复的问题。

#####   resolvePromise 中的 called 表示害怕有的人的promise写的不规范,resolve之后还能reject,所以加了called进行了限制。

const PENDING = "PENDING";
const SUCCESS = "FULFILLED";
const FAIL = "REJECTED";
// 严谨 应该判断 别人的promise 如果失败了就不能在调用成功 如果成功了不能在调用失败
function resolvePromise(promise2, x,resolve,reject) {
if(promise2 === x){
return reject(new TypeError('TypeError: Chaining cycle detected for promise #<Promise>'));
}
let called;
if(typeof x === 'function' || (typeof x === 'object' && x != null)){
try{
let then = x.then; // then 可能是getter object.defineProperty
if(typeof then === 'function'){ // {then:null}
then.call(x,y=>{
if(called) return; // 1)
called = true;
resolvePromise(promise2,y,resolve,reject);
},r=>{
if(called) return; // 2)
called = true;
reject(r);
})
}else{
resolve(x);
}
}catch(e){
if(called) return; // 3) 为了辨别这个promise 不能调用多次
called = true;
reject(e);
}
}else{
resolve(x);
}
}
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = value => {
if (this.status === PENDING) {
this.value = value;
this.status = SUCCESS;
this.onResolvedCallbacks.forEach(fn => fn());
}
};
const reject = reason => {
if (this.status === PENDING) {
this.reason = reason;
this.status = FAIL;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) { // .catch(function(){}) .then(null,function)
onFulfilled = typeof onFulfilled === 'function'?onFulfilled:val=>val;
onRejected = typeof onRejected === 'function'?onRejected:err=>{throw err}
let promise2;
promise2 = new Promise((resolve, reject) => {
if (this.status === SUCCESS) {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
});
}
if (this.status === FAIL) {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
});
}
if (this.status === PENDING) {
this.onResolvedCallbacks.push(()=>{
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
});
});
this.onRejectedCallbacks.push(()=> {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
});
});
}
});
return promise2;
}
}
// 希望测试一下这个库是否符合我们的promise A+规范
// promises-aplus-tests
Promise.defer = Promise.deferred = function(){
let dfd = {};
dfd.promise = new Promise((resolve,reject)=>{
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
module.exports = Promise;
// npm i promises-aplus-tests -g // promise 相关方法
// generator

  

  

promise的三种状态:

    • pending 等待状态
    • resolved 完成状态
    • rejected 拒绝状态

promise的三种状态,只能是pending->resolved或者pending->rejected,不能有其他类型的状态转换,并且状态一旦发生转换,就不再发生变化。

promise的方法:

1.then

2.all

3.race

上例子吧 :

例子1:在异步的读取完a1,a2,a3,a4,a5的文件之后,执行一个总的方法。

 'use strict';
//这是一个简单的应用
//要求:在异步读完a1.txt,a2.txt,a3.txt,a4.txt的时候执行一个总的方法
var Promise = require('bluebird');
var fs = require("fs") ; var promises = []; //Promise all方法的使用
for(var i = 1; i < 5; i++){
var promise = new Promise(function(resolve,reject){
fs.readFile("a" + i + ".txt","utf8",function (error,data){
if(error){
reject(error)
}else{
resolve(data)
}
}) ;
});
promises.push(promise);
} Promise.all(promises).then(function(data){
console.log(data);
}).catch(function(e){
console.log(e);
});
//

[ 'this is a1 !', 'this is a2 !', 'this is a3 !', 'this is a4 !' ]

例子2:在异步的读取a1,a2,a3,a4,a5的文件之后,只要有一个文件读取完成,就执行最后的方法。

 "use strict";

 var Promise = require("bluebird");
var fs = require("fs"); var promises = []; //Promise race方法的使用
for(var i = 1; i < 5; i++){
var promise = new Promise(function(resolve,reject){
fs.readFile("a" + i + ".txt","utf8",function (error,data){
if(error){
reject(error)
}else{
resolve(data)
}
}) ;
});
promises.push(promise);
}
Promise.race(promises).then(function(data){
console.log(data);
}).catch(function(e){
console.log(e);
})
//this is a1 !

例子3:要求:在读完a1.txt的时候读a2.txt,在读完a2.txt,读a3,然后a4.

 var a1 = new Promise(function(resolve,reject){
fs.readFile('a1.txt','utf8',function(error,data){
if(error){
reject(error);
}else{
resolve(data);
}
});
});
var ss = a1.then(function(){
return new Promise(function(resolve,reject){
fs.readFile('a2.txt','utf8',function(error,data){
if(error){
reject(error);
}else{
resolve(data);
}
});
});
}).then(function(){
return 'yanjinyun';
/*return new Promise(function(resolve,reject){
fs.readFile('a3.txt','utf8',function(error,data){
if(error){
reject(error);
}else{
resolve(data);
}
});
});*/
}).then(function(data){
return new Promise(function(resolve,reject){
fs.readFile('a4.txt','utf8',function(error,data){
if(error){
reject(error);
}else{
resolve(data);
}
});
});
}).catch(function(e){ });

#### 第一层的then和第二层的then

let aaa = new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(132)
},100)
});
aaa.then(data => {
console.log('--->>>>1', data)
return 'then1'
}).then(data => {
console.log('--->>>>3', data)
return 'then3'
});
aaa.then(data => {
console.log('--->>>>2', data)
}); // 结果
--->>>>1 132
--->>>>2 132
--->>>>3 then1

  

#### new Promise的时候promise里边的就执行了。

#### then如果不返回一个值的,默认返回undefined,算一个普通值。

let aaa = new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(132)
},100)
});
aaa.then(data => {
console.log('--->>>>1', data)
}).then(data => {
console.log('--->>>>3', data)
return 'then3'
});
aaa.then(data => {
console.log('--->>>>2', data)
});
--->>>>1 132
--->>>>2 132
--->>>>3 undefined

#### 只要有一个reject函数。后边的继续resolve。除非这个reject函数 报错。才会被catch到。

let aaa = new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(132)
},100)
});
aaa.then(data => {
console.log('--->>>>1', data)
throw new Error();
}, err => {
console.log('进入---err1')
return 'err1';
}).then(data => {
console.log('--->>>>3', data)
}, err => {
console.log('进入---err3')
// return 'err3'; // 写return 和 不写 return的区别在于 下边的resolve中接收到的值是不是undefined
throw new Error();
}).then(data => {
console.log('--->>>>4', data)
}, err => {
console.log('进入---err4')
return 'err4';
}).then(data => {
console.log('--->>>>5', data)
}, err => {
console.log('进入---err5')
return 'err5';
}).catch(e => {
console.log(e + '---');
});
aaa.then(data => {
console.log('--->>>>2', data)
});
--->>>>1 132
--->>>>2 132
进入---err3
进入---err4
--->>>>5 err4
 
 

#### resolve(new Error('error')) 结果也是正常执行的。

##### promise的defer实现。

Promise.defer = Promise.deferred = function(){
let dfd = {};
dfd.promise = new Promise((resolve,reject)=>{
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
// 没用defer之前
function read(url) {
return new Promise((resolve, reject) => {
fs.readFile(url, 'utf-8', (err, data) => {
if(err) reject(err);
resolve(data);
})
})
} // 用了defer之后
function read(url) {
let defer = Promise.defer();
fs.readFile(url, 'utf-8', (err, data) => {
if(err) defer.reject(err);
defer.resolve(data);
})
return defer.promise;
}

  

#### race 只要有一个失败了就失败了

// 测试只要有一个race 中只要有一个promise reject了,那么久reject了。
let aa = () => {
return new Promise(function(resolve, reject) {
setTimeout(() => {
reject(1);
},1000)
})
} let bb = () => {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(2);
},2000)
})
}
Promise.race([aa(), bb()]).then(data => {
console.log(data);
}).catch(e => {
console.log('e', e);
}) // e 1

#### generator

### promisify 的用法

function promisify(fn){ // node中 util模块自带了这个功能
return function(...args){ // args = [name,'utf8']
return new Promise((resolve,reject)=>{
fn(...args,function(err,data){
if(err) reject(err);
resolve(data);
}); // fs.readFile('name.txt','utf8);
})
}
}
// let readFile = promisify(fs.readFile);
Promise.all([1,fs.readFile('./name.txt','utf8'),fs.readFile('./age.txt','utf8')]).then(data=>{
return 100
},err=>{
console.log(err);
}).then(data=>{
});

  

#### promise 的  finally

- 无论前边是catch还是finally都是执行。

- 只要前边的catch捕获到了错误,后边的then仍然会执行。后边的then的值是catch的返回值。

- finally 并不会捕获错误,如果发生错误finally前边没有捕获的话,finally仍然会执行,后边的catch仍然会去捕获。

- finallly 像一个不会产生返回值的中间器。

promise的学习的更多相关文章

  1. JavaScript 标准内置对象Promise使用学习总结

    Javascript标准内置对象Promise使用学习总结   by:授客 QQ:1033553122 1.   基础用法 var condition = true; let p = new Prom ...

  2. JavaScript中 Promise的学习以及使用

    今天一个哥们发过来一段js代码,没看懂,就顺便学习了一下,代码如下  Promise.resolve('zhangkai').then(value => {console.log(value)} ...

  3. Promise 基础学习

    Promise 是ES6的特性之一,采用的是 Promise/A++ 规范,它抽象了异步处理的模式,是一个在JavaScript中实现异步执行的对象. 按照字面释意 Promise 具有"承 ...

  4. promise的学习心得记录

    这里只讲promise,和async的使用方法,不会讲他们的原理. Promise 是异步编程的一种解决方案,可以用于取代传统的回调函数,该变那些函数层层嵌套调用的尴尬局面. 1)promise 基本 ...

  5. Javascript Promise对象学习

    ES6中的Promise对象 var p = new Promise(function(resolve, reject){ window.setTimeout(function(){ console. ...

  6. ES6的promise的学习

    1.Promise的含义: Promise是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大.它由社区最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了Pro ...

  7. promise 的学习

    promise 是为了解决异步操作的顺序问题而产生的 特性 promise 的实例一旦创建就会执行里面的异步操作 promise 的实例状态一旦改变就变成凝固的了, 无法再对其作出修改,  (不明白为 ...

  8. [javascript] Promise简单学习使用

    原文地址:http://www.cnblogs.com/dojo-lzz/p/4340897.html 解决回调函数嵌套太深,并行逻辑必须串行执行,一个Promise代表一个异步操作的最终结果,跟Pr ...

  9. JavaScript Promise的学习笔记

    首先声明:本人今天刚接触Promise,通过一个例子,希望能更好的来理解,如果有不对的地方,还望指正 Promise是专门为解决 js中回调而引起的各种问题,而产生的. 在异步编程中,我们经常使用回调 ...

随机推荐

  1. iOS 获取版本号(Swift和OC两种)

    iOS获取应用版本号:version OC: [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVers ...

  2. Android工程师入门(一)——这周入大门,挤时间,轻喷

    挤挤时间,入个门先. 一.环境搭建 略. 二.项目结构 在studio中,项目=Module: res:放置应用到的所有资源——基本决定了生成的APK的大小: java:java源程序: manife ...

  3. 单机搭建Android开发环境(三)

    单机搭建Android开发环境,第一篇重点介绍了如何优化Windows 7系统,以提高开发主机的性能并延长SSD的使用寿命.第二篇重点介绍了基于VMWare安装64位版的Ubuntu 12.04,并安 ...

  4. 北理工c语言期末考试

    1 给定一个区间,输出其中前半部分数字之和等于后半部分数字之和的数,没有则输出No output.(15分) 题目内容: 给定一个区间,输出其中前半部分数字之和等于后半部分数字之和的数,没有则输出No ...

  5. 关于AngularJs中的路由学习总结

    AngularJs中的路由,应用比较广泛,主要是允许我们通过不同的url访问不同的内容,可实现多视图的单页web应用.下面看看具体怎么使用. 关于路由  通常我们的URL形式为http://jtjds ...

  6. [No000006]苏格拉底与失恋者的对话

    苏(苏格拉底): 孩子,为什么悲伤? 失(失恋者): 我失恋了. 苏: 哦,这很正常. 如果失恋了没有悲伤,恋爱大概也就没有什么味道了.可是,年轻人,我怎么发现你对失恋的投入甚至比对恋爱的投入还要倾心 ...

  7. 深入理解Linux修改hostname(转载)

    http://www.cnblogs.com/kerrycode/p/3595724.html http://www.centoscn.com/CentOS/config/2014/1031/4039 ...

  8. Linux下误删除后的恢复操作(ext3/ext4)

    Linux是作为一个多用户.多任务的操作系统,文件一旦被删除是难以恢复的.尽管删除命令只是在文件节点中作删除标记,并不真正清除文件内容,但是其他用户和一些有写盘动作的进程会很快覆盖这些数据.在日常工程 ...

  9. HashTable, HashMap, LinkedHashMap, ConcurrentHashMap

    HashTable: 不允许null的key或value, 线程安全 HashMap: 允许一个null的key, 无限的null value, 非线程安全 LinkedHashMap: HashMa ...

  10. BZOJ 2957 楼房重建

    Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些 ...