Promise 入门与使用
Tags: ECMAScript6
参考资料
Promise最初被提出是在 E语言中, 它是基于并列/并行处理设计的一种编程语言。
概念
ES6规定,Promise对象是一个构造函数,用来生成Promise实例。
规范:Promises -> Promises/A -> Promises/A+
状态
Promise实例生成以后处于pending状态,可以用then方法分别指定Resolved状态和Reject状态的回调函数。
ES6 Promise 使用
API
- Promise.prototype.constructor
- Promise.prototype.then
- Promise.prototype.catch
- Promise.all
- Promise.race
- resolve
- reject
基本用法
var promise = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("success");
}, 500);
//reject(error);
});
promise
.then(function (value) {
//success
console.log(value);
return "over"
}, function (value) {
//error
console.log(value);
});
console.log("hello");
//"hello"
//"success"
链式调用
then方法执行后会返回另一个promise,它的状态会传递给下一个then,如果没有显示的在回调函数中指定返回的promise对象,那么引擎会帮你生成一个promise并且执行其resolve方法,并且把你的回调函数传入其中。
function asynchData (msg) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(msg);
}, 100);
});
}
asynchData("step1")
.then(function (value) {
//success
console.log(value);
return asynchData("step2")
})
.then(function (value) {
console.log(value);
})
//"step1"
//"step2"
asynchData("step2")
.then(function (value) {
//success
console.log(value);
return "success";
})
.then(function (value) {
console.log(value);
})
//"step1"
//"success"
本身then、catch方法默认的返回是一个新的Promise对象
function asynchData (msg) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(msg);
}, 100);
});
}
var stepOne = asynchData("stepone");
var stepTwo = stepOne.then(function (val) {
console.log(val);//stepone
});
var stepThree = stepTwo.then(function (val) {
console.log(val);//undefined
});
var stepThree2 = stepTwo.then(function (val) {
console.log(val);//undefined
});
var catchStep = stepThree.catch(function (err) {
console.log(err);
});
console.log(stepTwo instanceof Promise);//true
console.log(stepThree instanceof Promise);//true
console.log(stepThree2 instanceof Promise);//true
console.log(catchStep instanceof Promise);//true
error处理:catch
其实catch是then(null, function(){...})的别名,实质上是相等的。注意一点,没有使用catch方法指定错误处理的回调函数,Promise对象抛出的错误不会传递到外层代码,即不会有任何反应。所以为了不给自己找麻烦尽量编写catch方法
function asynchData (msg) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
//Promise指定在下一轮“事件循环”再抛出错误,结果由于没有指定catch语句,就冒泡到最外层,成了未捕获的错误。
throw new Error('async error!');
}, 1000);
throw new Error('error!');
});
}
asynchData("step1")
.then(function (value) {
//success
console.log(value);
})
.catch(function (err) {
console.log(err);
//如果Promise状态已经变成resolved,再抛出错误是无效的。
//Promise对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。
});
//"Error: error!"
asynchData("step2")
.then(function (value) {
//success
console.log(value);
})
.then(null, function (err) {
console.log(err);
});
//"Error: error!"
这里有一个要注意的点:如果你一旦指定catch方法或者你在then方法里指定了reject方法,那么你指定的catch方法会捕获住异常,并且异常不再继续传递下去,无论你在catch里返回什么!除非catch方法里还有报错、或者返回一个reject状态的promise
function asynchData (msg) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
reject(msg);
}, 100);
});
}
asynchData("I am error")
.then(function () {
//resolve callback
}, function (err) {
//reject callback
console.log(err + "from reject callback")
})
.catch(function (err) {
//err callback
console.log(err + " from catch callback");//catch callback无法执行,因为上一个then已经指定了reject处理方法
})
// I am errorfrom reject callback
asynchData("I am error too")
.then(function () {
//resolve callback
}, function (err) {
//reject callback
console.log(err + "from reject callback");
throw new Error("I from reject callback error");
})
.catch(function (err) {
//err callback
console.log(err + " from catch callback");
//catch callback会被执行,并且接收的错误是从上一个reject方法返回的
//上一个then方法抛出异常,then返回一个reject状态的promise,并且被下一个catch方法捕获住
})
//I am error toofrom reject callback
//Error: I from reject callback error from catch callback
同步or异步
试想下如果让你写一个api,其中有一个参数是callback形式传入,那么方法体内该是以何种形式执行callback呢?是同步呢还是异步执行呢?为了保持API的统一,我们定义callback在方法里都是以异步方式执行的。
关于这个问题,在 Effective JavaScript 的 第67项 不要对异步回调函数进行同步调用 中也有详细介绍。
绝对不能对异步回调函数(即使在数据已经就绪)进行同步调用。
如果对异步回调函数进行同步调用的话,处理顺序可能会与预期不符,可能带来意料之外的后果。
对异步回调函数进行同步调用,还可能导致栈溢出或异常处理错乱等问题。
如果想在将来某时刻调用异步回调函数的话,可以使用 setTimeout 等异步API。
Effective JavaScript
— David Herman
了避免同时使用同步、异步调用可能引起的混乱问题,Promise在规范上规定 Promise只能使用异步调用方式。
var promise = new Promise(function (resolve) {
console.log("inner promise"); // 1
resolve(42);
});
promise.then(function (value) {
console.log(value); // 3
});
console.log("outer promise"); // 2
// inner promise
// outer promise
// 42
Promise保证了每次调用都是以异步方式进行的,所以我们在实际编码中不需要调用 setTimeout 来自己实现异步调用。
多个promise:all
function asynchData (msg, toReject) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
if (toReject) {
reject(msg + " failure!!!");
} else {
resolve(msg);
}
}, 100);
});
}
Promise.all([asynchData("step1"), asynchData("step2"), asynchData("step2")]).then(function (value) {
console.log(value);//["step1", "step2", "step2"]
});
Promise.all([asynchData("step1", true), asynchData("step2", true), asynchData("step2")]).then(
function (value) {
console.log(value);//["step1", "step2", "step2"]
},
function (value) {
console.log(value);//step1 failure!!!
//之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值
}
);
处理reject
function asynchData (msg, toReject) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
if (toReject) {
reject(msg + " failure!!!");
} else {
resolve(msg);
}
}, 100);
});
}
//之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给p的回调函数
Promise.race([asynchData("step1"), asynchData("step2"), asynchData("step2")]).then(function (value) {
console.log(value);//"step1"
});
一些例子
我们定义A、B、C三个方法,并且都是异步的。我们希望A成功后执行B,失败执行C,B失败后执行C。想想改如何实现呢?
function asynchData (msg, toFail) {
return new Promise(function (resolve, reject) {
console.log(msg);
if (toFail) {
reject();
} else {
resolve();
}
});
}
asynchData("A")
.then(function () {
return asynchData("B");
})
.then(null, function () {
asynchData("C")
});
这样写是不是就达到目的了?
Deferred & Promise 关系
我们经常见到jquery.Deferred,但是和Promise有什么关系呢?Deferred和Promise不同,它没有共通的规范,每个Library都是根据自己的喜好来实现的。
- Deferred 拥有 Promise
- Deferred 具备对 Promise的状态进行操作的特权方法
相信我们使用promise后会给我们带来耳目一新的感觉,减少我们的callback hell的出现频率,大大的增强我们代码的可维护性!
Promise 入门与使用的更多相关文章
- Promise入门到精通(初级篇)-附代码详细讲解
Promise入门到精通(初级篇)-附代码详细讲解 Promise,中文翻译为承诺,约定,契约,从字面意思来看,这应该是类似某种协议,规定了什么事件发生的条件和触发方法. Pr ...
- promise入门基本使用
Promise入门详解和基本用法 异步调用 异步 JavaScript的执行环境是单线程. 所谓单线程,是指JS引擎中负责解释和执行JavaScript代码的线程只有一个,也就是一次只能完成一项任 ...
- 一.Promise入门准备阶段
一.Promise入门准备阶段 1.区别实例对象呵函数对象 2.两种类型的回调函数(同步与异步) 2.1 同步回调 2.2 异步回调 3.JS的error处理 3.1 错误的类型 3.2 错误处理与错 ...
- Javascript Promise入门
是什么? https://www.promisejs.org/ What is a promise? The core idea behind promises is that a promise r ...
- promise入门demo
<!DOCTYPE html> <html> <head> <title></title> </head> <body&g ...
- javaScript Promise 入门
Promise是JavaScript的异步编程模式,为繁重的异步回调带来了福音. 一直以来,JavaScript处理异步都是以callback的方式,假设需要进行一个异步队列,执行起来如下: anim ...
- Promise入门详解
异步调用 异步 JavaScript的执行环境是单线程. 所谓单线程,是指JS引擎中负责解释和执行JavaScript代码的线程只有一个,也就是一次只能完成一项任务,这个任务执行完后才能执行下一个,它 ...
- ES6中Promise的入门(结合例子)
一.Promise的前言 解决回调地狱 //以往回调方式 函数1(function(){ //代码执行...(ajax1) 函数2(function(){ //代码执行...(ajax2) 函数3(f ...
- 细说Promise
一.前言 JavaScript是单线程的,固,一次只能执行一个任务,当有一个任务耗时很长时,后面的任务就必须等待.那么,有什么办法,可以解决这类问题呢?(抛开WebWorker不谈),那就是让代码异步 ...
随机推荐
- Docker 三大核心工具
Docker-machineDocker Machine是一个简化Docker安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker,比如VirtualBox. Digital Oc ...
- SQL之相关语法及操作符
概述:UNION.SELECT INTO.INSERT INTO SELECT.SQL约束 UNION操作符 UNION操作符用于合并两个或多个SELECT语句的结果集 请注意,UNION内部的每个S ...
- ExtJs4学习(二):Dom操作
如今主流的JS框架要数ExtJs和JQuery应用的比較广泛.JQuery属于轻量级的,一般做站点应用比較常见.可见块头小的优势. ExtJs比較庞大,它除了对主要的JS语法和HTML DOM操作方式 ...
- java线程用法
package com; public class Demo { public static void main(String[] args) { // TODO Auto-generated met ...
- spark on yarn 配置history server
spark在yarn模式下配置history server 1.建立hdfs文件– hadoop fs -mkdir /user/spark– hadoop fs -mkdir /user/spark ...
- Linux 进程状态 说明
Linux是一个多用户,多任务的系统,可以同时运行多个用户的多个程序,就必然会产生很多的进程,而每个进程会有不同的状态. 在下文将对进程的 R.S.D.T.Z.X 六种状态做个说明. 进程状态: S ...
- python 基础 6.0 异常的常用形式
一. 异常 异常既是一个时间,该事件会在程序执行过程中发生,影响了程序的正常执行.一般情况下,在python无法正常处理程序时就会发生一个异常.异常是python对象,表示一个错误.当python ...
- Intellij IDEA创建的Web项目配置Tomcat并启动Maven项目(转)
大部分是直接上图哦. 点击如图所示的地方,进行添加Tomcat配置页面 弹出页面后,按照如图顺序找到,点击+号 tomcat Service -> Local 注意,这里不要选错了哦,还有一个T ...
- PHP 格式化数字串
在xls或csv文件中, 超过12位以上的数字会被"科学计数", 所以当php读取这些文件的时候, 会读成 420E+16 , 显然这不是我们想要的, 所以就要用到数字格式化了! ...
- python cookbook第三版学习笔记十三:类和对象(四)描述器
__get__以及__set__:假设T是一个类,t是他的实例,d是它的一个描述器属性.读取属性的时候T.d返回的是d.__get__(None,T),t.d返回的是d.__get__(t,T).说法 ...