Promise对象

一.含义

1. Promise是什么

  • promise是异步编程的一种解决方案,比传统的异步解决方案【回调函数】和【事件】更合理,更强大,已被纳入ES6规范

2. 实例讨论

问题:发送多个异步请求 并且每个请求之间需要相互依赖

  1. 在传统方法中,使用回调函数,通过嵌套方式来解决这个问题

    • 问题:
    • 代码逻辑书写顺序与执行顺序不一致,不利于阅读与维护。
    • 异步操作的顺序变更时,需要大规模的代码重构。
    • 回调函数基本都是匿名函数,bug 追踪困难。
    • 回调函数是被第三方库代码(如上例中的 ajax )而非自己的业务代码所调用的,造成了 IoC 控制反转
    $.get(url, data1 => {
    console.log(data1)
    $.get(data1.url, data2 => {
    console.log(data1)
    })
    })
  2. Promise处理多个互相关联的异步请求

    const request = url => {
    return new Promise((resolve, reject) => {
    $.get(url, data => {
    resolve(data)
    });
    })
    }; // 请求data1
    request(url).then(data1 => {
    return request(data1.url);
    }).then(data2 => {
    return request(data2.url);
    }).then(data3 => {
    console.log(data3);
    }).catch(err => throw new Error(err));

二.Promise特性案例解析

1. Promise的立即执行性

  • promise对象表示未来将要发生的事件,但是在创建Promise对象时,作为参数的方法是会立即执行的,只是其中执行的代码可以是异步代码

  • 所以如下案例,create promise会先于after create promise执行

    var p = new Promise(function(resolve,reject){
    console.log('cerete promise');
    resolve('success');
    }) console.log('after create promise'); p.then(function(value){
    console.log(value);
    }) // create promise
    // after create promise
    // success

2. promise的三种状态

var p1 = new Promise(function(resolve,reject){
resolve(1);
});
var p2 = new Promise(function(resolve,reject){
setTimeout(function(){
resolve(2);
}, 500);
});
var p3 = new Promise(function(resolve,reject){
setTimeout(function(){
reject(3);
}, 500);
}); console.log(p1);
console.log(p2);
console.log(p3);
setTimeout(function(){
console.log(p2);
}, 1000);
setTimeout(function(){
console.log(p3);
}, 1000); p1.then(function(value){
console.log(value);
});
p2.then(function(value){
console.log(value);
});
p3.catch(function(err){
console.log(err);
});
  • 返回值
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 1}
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
1
2
3
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 2}
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: 3}
  • promise有三种状态,pending,resolved,rejected
  • 当promise刚创建时,处于pending状态
  • 当promise中的参数函数执行resolve之后,promise由pending状态变为resolved状态
  • 当promise中的参数函数执行reject之后,那么promise中的pending状态变为rejected状态

3. Promise的状态不可逆性

var p1 = new Promise(function(resolve, reject){
resolve("success1");
resolve("success2");
}); var p2 = new Promise(function(resolve, reject){
resolve("success");
reject("reject");
}); p1.then(function(value){
console.log(value);
}); p2.then(function(value){
console.log(value);
});
  • 返回结果
success1
success
  • promise中的状态一旦变成 resolved或者rejected之后,无论后续怎么调用resolve和reject方法,都无法改变promise的状态

4. 链式调用

var p = new Promise(function(resolve, reject) {
resolve(1);
});
p.then(function(value) { //第一个then
console.log(value);
return value * 2;
}).then(function(value) { //第二个then
console.log(value);
}).then(function(value) { //第三个then
console.log(value);
return Promise.resolve('resolve');
}).then(function(value) { //第四个then
console.log(value);
return Promise.reject('reject');
}).then(function(value) { //第五个then
console.log('resolve: ' + value);
}, function(err) {
console.log('reject: ' + err);
})
  • 返回结果
1
2
undefined
resolve
reject:reject
  • promise的then方法,返回一个新的promise对象。因此可以通过链式条用then方法
  • then方法接受两个函数作为参数,第一个是promise执行成功的时候调用的方法,第二个是promise执行失败的时候调用的方法
  • 以上两个函数中,只有一个会被调用

5. Promise then,回调异步性

var p = new Promise(resolve,reject){
resolve("success");
};
p.tnen(function(value){
console.log(value);
});
console.log("which one is first~");
  • 返回结果
which one is first~
success
  • Promise接收函数是同步执行的,但是then方法中的函数是异步执行的,所以success是后面执行的

6. Promise中的异常

var p1 = new Promise(function(resolve, reject) {
foo.bar();
resolve(1);
}); p1.then(
function(value) {
console.log('p1 then value: ' + value);
},
function(err) {
console.log('p1 then err: ' + err);
}
).then(
function(value) {
console.log('p1 then then value: ' + value);
},
function(err) {
console.log('p1 then then err: ' + err);
}
); var p2 = new Promise(function(resolve, reject) {
resolve(2);
}); p2.then(
function(value) {
console.log('p2 then value: ' + value);
foo.bar();
},
function(err) {
console.log('p2 then err: ' + err);
}
).then(
function(value) {
console.log('p2 then then value: ' + value);
},
function(err) {
console.log('p2 then then err: ' + err);
return 1;
}
).then(
function(value) {
console.log('p2 then then then value: ' + value);
},
function(err) {
console.log('p2 then then then err: ' + err);
}
);
  • 返回值
p1 then err: ReferenceError: foo is not defined
p2 then value: 2
p1 then then value: undefined
p2 then then err: ReferenceError: foo is not defined
p2 then then then value: 1
  • Promise中的异常由then的第二个参数函数进行处理,异常信息将作为promise的值
  • 异常一旦得到处理,then返回的后续Promise对象将恢复正常,并被promise执行成功的回调函数进行处理
  • 另外要注意的是p1,p2的多级then是交替执行的

7. Promise.resolve()

  • Promise.resolve()可以接受一个值或者是一个promise对象

    • 当参数值为普通时,它返回一个resolved状态的promise对象,值为传的那个参数
    • 当参数值为promise对象时,它直接返回这个promise对象

8. resolve VS reject

var p1 = new Promise(function(resolve, reject){
resolve(Promise.resolve('resolve'));
}); var p2 = new Promise(function(resolve, reject){
resolve(Promise.reject('reject'));
}); var p3 = new Promise(function(resolve, reject){
reject(Promise.resolve('resolve'));
}); p1.then(
function fulfilled(value){
console.log('fulfilled: ' + value);
},
function rejected(err){
console.log('rejected: ' + err);
}
); p2.then(
function fulfilled(value){
console.log('fulfilled: ' + value);
},
function rejected(err){
console.log('rejected: ' + err);
}
); p3.then(
function fulfilled(value){
console.log('fulfilled: ' + value);
},
function rejected(err){
console.log('rejected: ' + err);
}
);
  • 返回结果
p3 rejected: [object Promise]
p1 fulfilled: resolve
p2 rejected: reject
  • Promise回调函数中的第一个参数resolve,会对Promise执行’拆箱‘动作。即当resolve的参数是一个promise对象时,resolve会拆箱获取这个promise对象的值,但是这个过程是异步的。
  • Promise回调函数中的第二个参数reject不会进行拆箱操作,所以reject函数中的参数直接传递给then方法中的rejected回调

三.Promise使用总结

  1. 初始化Promise对象

    • new Promise(fn)
    • Promise.resolve(fn)
  2. 调用上一步返回的promise实例对象的then方法,注册回调函数

    • then回调函数可以拥有一个参数,也可以不带参数。如果then中的回调函数依赖上一层返回的结果,那么要带上参数

      new Promise(fn)
      .then(fn(value){
      //处理过程
      })
  3. 最后注册 catch 异常处理函数,处理前面回调中可能抛出的异常。

16. Promise对象的更多相关文章

  1. angular学习笔记(二十八-附2)-$http,$resource中的promise对象

    下面这种promise的用法,我从第一篇$http笔记到$resource笔记中,一直都有用到: HttpREST.factory('cardResource',function($resource) ...

  2. ES6深入学习记录(二)promise对象相关

    1.Promise的含义 Promise是异步编程的一种解决方案,比传统的解决方案--回调函数和事件更合理和强大.ES6将其写进了语言标准,统一了用法,原生提供了promise对象. 所谓Promis ...

  3. 16 Promise

    Promise 特点 对象的状态不受外界影响.Promise对象代表一个异步操作,有三种状态:Pending(进行中).Resolved(已完成,又称Fulfilled)和Rejected(已失败). ...

  4. es6中的promise对象

    Promise是异步里面的一种解决方案,解决了回调嵌套的问题,es6将其进行了语言标准,同意了用法,提供了`promise`对象, promise对象有三种状态:pending(进行中) .Resol ...

  5. ES6的promise对象应该这样用

    ES6修补了一位Js修真者诸多的遗憾. 曾几何时,我这个小白从js非阻塞特性的坑中爬出来,当我经历了一些回调丑陋的写法和优化的尝试之后,我深深觉得js对于多线程阻塞式的开发语言而言,可能有着其太明显的 ...

  6. Angularjs promise对象解析

    1.先来看一段Demo,看完这个demo你可以思考下如果使用$.ajax如何处理同样的逻辑,使用ng的promise有何优势? var ngApp=angular.module('ngApp',[]) ...

  7. JavaScript异步编程(1)- ECMAScript 6的Promise对象

    JavaScript的Callback机制深入人心.而ECMAScript的世界同样充斥的各种异步操作(异步IO.setTimeout等).异步和Callback的搭载很容易就衍生"回调金字 ...

  8. Promise对象

    1.Promise思想:每一个异步任务立刻返回一个Promise对象,由于是立刻返回,所以可以采用同步操作的流程.这个Promises对象有一个then方法,允许指定回调函数,在异步任务完成后调用. ...

  9. angularJS中的Promise对象($q)的深入理解

    原文链接:a better way to learn AngularJS - promises AngularJS通过内置的$q服务提供Promise编程模式.通过将异步函数注册到promise对象, ...

随机推荐

  1. 09-cmake语法-add_dependencies()

    在编译器的命令行上,为当前路径以及下层路径的源文件加入一些define flag.这个命令可以用来引入任何flag,但是它的原意是用来引入预处理器的定义.那些以-D或/D开头的.看起来像预处理器定义的 ...

  2. springboot 整合 mybatis 入门

    springboot整合mybatis 0.yml 配置文件 1.创建数据库表. 2.创建实体类. 3.创建 Mapper 接口 ,添加 @Mapper 注解. 4.创建 Mapper 映射文件. & ...

  3. 常用.Net 6.0 新特性

    1.nameof表达式.Nameof表达式可以直接返回对象定义的名称,比如参数.枚举.变量. 控件.属性等.可以大大减少硬编码的使用,提高程序灵活性. }, 2.字符串嵌入值($). MsgBox.S ...

  4. 【JZOJ5739】【20190706】毒奶

    题目 有\(n\)个现实城市,另有\(n\)个幻想城市 原图中在现实城市存在\(m\)条边,在幻想城市存在\(m-1-n\)条边 一个排列是合法的当且进当显示城市 \(i\) 向幻想城市 \(p_i\ ...

  5. 三天精通Vue--ES6的常用语法

    详细学习请参考  阮一峰的ECMAScript 6 入门 let和const的使⽤ es5中使用var来声明全局变量 es5中我们学习了使用var来声明变量,但是使用var声明变量,会存在变量提升的问 ...

  6. linux .pid文件简述

    PID全称是Process Identification. PID是进程的代号,每个进程有唯一的PID编号.它是进程运行时系统随机分配的,并不代表专门的进程.在运行时PID是不会改变标识符的,但是你终 ...

  7. UID、PID、PPID是什么?

    UID是用户ID,PID是进程ID,PPID是父进程ID. UID UID 用户身份证明(User Identification)的缩写.UID用户在注册后,系统会自动的给你一个UID的数值.意思就是 ...

  8. base64和Blob互相转换

      1.base64转blob(二进制数据) /** * 将以base64的图片url数据转换为Blob * @param urlData 用url方式表示的base64图片数据 */ functio ...

  9. javascript 检测浏览类型和版本

    废话不多说了,直接就上代码吧,因为IE11以后的版本和之前的不一样了,所以有些关键字还需要注意.这里面判断IE的时候需要多注意.function getBrowserInfo(){ var ua = ...

  10. 1-7docke的网络模式

    1.Bridge模式 bridge 模式是 docker 的默认⽹络模式,不写 –net 参数,就是 bridge 模式.比如使⽤ docker run - p 时 工作模式从网上找了一个,如下 例子 ...