ES6学习教程之Promise用法详解

前言

promise用了这么多年了,一直也没有系统整理过。今天整理整理promise的相关东西,感兴趣的可以一起看一看。我尽量用更容易理解的语言来剖析一下promise

我准备分两篇文章来说明一下promise

一篇来理解和使用promise(本篇) 另一篇来从promise使用功能的角度来剖析下promise的源码(下一篇)

1、什么是Promise

我的理解是:实现让我们用同步的方式去写异步代码的一种技术。是异步解决方案的一种。

他可以将多个异步操作进行队列化,让它们可以按照我们的想法去顺序执行。

那么,Promise之前有没有其他的异步解决方案。肯定是有的,常见的有callback回调函数以及事件。

那Promise有啥优势,我认为Promise功能更为强大,且能让我们代码写的更为清晰

  • Promise提供了统一的API, 让我们控制异步操作更加容易
  • Promise可以避免callback回调函数的层层嵌套,使代码更为清晰。可读性性与维护性更高

2、Promise基本用法

首先,我们先来了解一些Promise的基本概念

2.1、Promise状态

Promise一共有3中状态,分别是Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)
状态的改变只可能从Pending转------>Resolved,或者从Pending------->Rejected。并且状态一旦发生改变,就不会再更改了。而触发状态发生改变的,只有异步操作的结果。结果为成功 触发状态变更为 Resolved, 结果失败或者中途发生错误,则会触发状态变更为 Rejected

2.2 Promise结构

Promise是一个构造函数,故通过new Promise()可以实例化出来一个Promise对象

new Promise()时,接受一个函数作为参数,且这个函数,有两个参数,分别是resolve,reject。 而resolve和 reject也是两个函数。他们由JavaScript引擎提供,不用自己部署。

每一个被实例化出来的promise实例,都有.then() 和 .catch() 两个方法。且这两个方法的调用支持链式操作

好,了解完概念,我们看看Promise的基本用法

首先,如何实例化一个promise对象

const promise = new Promise((resolve, reject) => {
	setTimeout(() => {
		if (/* 成功 */) {
			resolve(res)
		} else {
			reject(err)
		}
	}, 100)
})

上图中,通过new Promise() 实例化了一个promise实例,注意:new Promise()方法中的函数是一个立即执行函数,即,在new Promise()的一瞬间就会被执行。函数内代码是同步代码。

resolve和reject用于返回异步操作的结果,当使用resolve()时,promise状态会由Pending—>Resolved, 并将异步的正确结果返回。当使用reject()时,promise状态由Pending---->Rejected,并将错误信息返回

再看这个对象如何接收返回的结果

promise.then((res) => {
	console.log(res)
}).catch((err) => {
	console.log(err)
})

上图中,.then的回调函数 和 .catch的回调函数分别用来接收resolve()返回的正确信息和reject返回的错误信息。

下面我们来详细看下.then() 和 .catch()

.then() 函数

then()函数是Promise实例的一个方法,他的作用是为Promise实例添加状态改变时的回调函数
它存在以下特点

  1. then()是添加在Promise的原型上的。即Promise.prototype.then(), 故所有Promise实例都存在.then()方法
  2. .then()可以进行链式操作 即promise.then().then().then(),then的回调函数将会按照次序调用
  3. .then()函数存在两个参数,这两个参数一般情况下是函数。其中,第一个函数是在状态变为Resolved的时候才会执行(我们下文中统称为.then的resolve回调),并且参数是Promise对象resolve(res)时的值。第二个函数是在状态变为Rejected的时候才会执行(我们下文统称为.then的reject回调),后面我们会说哪几种情况下,状态会变成Rejected
  4. Promise会存在值穿透的情况,当我们then()的两个参数不为函数时,会穿透到下一个then()里面,如果下一个then()参数也不是函数,则会继续向下穿透
  5. 我们上面说过了,Promise实例resolve()方法执行时,会将实例的状态变更为Resolved,故.then的resolve回调会在当前Promise实例resolve()时被触发

下面,我们重点来分析下第2,3,4,5

function getData(url) {
 return new Promise((resolve, reject) => {
 setTimeout(() => {
  if (url) {
  resolve({
   code: 200,
   message: 'ok',
   data: 123
  })
  } else {
  reject(new Error('缺少url'))
  }
 }, 100)
 })
}
getData('http://www.baidu.com').then((res) => {
 console.log('第一个回调')
 console.log(res)
}).then((res) => {
 console.log('第二个回调')
 console.log(res)
}).then((res) => {
 console.log('第三个回调')
 console.log(res)
})
// 第一个回调
// { code: 200, message: 'ok', data: 123 }
// 第二个回调
// undefined
// 第三个回调
// undefined

可以看出,首先,当getData() resolve() 执行时 .then的resolve回调函数被依次调用,但是只有第一个then()的resolve回调函数的参数有值,而其他两个是undefind,这是为什么呢?我们再来看一个代码

getData('http://www.baidu.com').then((res) => {
 console.log('第一个回调')
 console.log(res)
 return Promise.resolve()
}).then((res) => {
 console.log(res)
})
// 第一个回调
// { code: 200, message: 'ok', data: 123 }
// undefined

看这个代码我们可以发现,上一个then的resolve回调当return一个Promise.resolve()时,和我们不return 任何东西时得到的结果是一样的。那我们是不是可以理解为,每个.then()方法的resolve回调函数,执行完后默认都会返回一个Promise.resolve()。没错,我告诉你,是的。

至于Promise.resolve()得到的是一个什么,我先告诉你,他得到的是一个resolve状态的Promise实例。这个后面我们会再讲。

此时,我们可以总结出:从第二个.then()开始,调用这个.then的resolve回调函数的-----是上一个.then的resolve回调所返回的Promise实例。而.then回调函数的参数,便是上一个.then的回调函数所返回的Promise实例resolve的值。下面我们看一段代码验证一下

getData('http://www.baidu.com').then((res) => {
 console.log('第一个回调')
 console.log(res)
 return new Promise((resolve, reject) => {
 resolve('123')
 })
}).then((res) => {
 console.log(res)
})

// 第一个回调
// { code: 200, message: 'ok', data: 123 }
// 123

总结:

  1. 每一个.then的resolve回调都会返回默认返回一个Resolved状态的Promise对象
  2. 当你收到return了一个新的Promise实例时,会覆盖默认返回的Promise实例
  3. 返回的Promise实例resolve()的值,会作为下一个.then的resolve回调的参数返回

下面我们再来看下,如果then()的参数不是函数,那会怎么样,下面,我们看一段代码

var getData = function() {
 return new Promise(function(resolve, reject) {
  resolve(123)
 });
};
getData().
then(345)
.catch(err => {
 console.log('捕捉到一个错误')
 console.log(err)
}).then((res) => {
 console.log('我是第二个then')
 console.log(res)
})
// 输出
我是第二个then
123

如上图,可以看到,当我们第一个then的resolve回调不是函数,而是一个数字345时,resolve(123)穿透到第二个then中了,触发了第二个then的resolve回调执行,并将resolve的返回值给了第二个then的resolve回调。这种现象,叫做值穿透。

var getData = function() {
 return new Promise(function(resolve, reject) {
  reject(new Error(123))
 });
};
getData().
then(345)
.catch(678)
.then((res) => {
 console.log('我是第二个then')
 console.log(res)
}).catch(err => {
 console.log('我是第二个catch')
 console.log(err)
})
// 输出
我是第二个catch
Error: 123

可以看到,报错时,同样发生了值穿透

到此,.then()相关以及 then()的第一个参数就讲完了,而第二个参数,我们放到.catch()方法中一起将

.catch() 函数

catch()也是挂载在Promise对象原型下的方法(Promise.prototype),和then()一样, 故所有Promise对象也都有catch方法。它的作用是用来指定发生错误时的回调函数,也就是捕获异步操作所发生的错误
它有什么特点呢。我们先总结一下,后来再一一来验证

  1. .catch()会指定一个参数作为错误发生时的回调,故catch((err) => {})的参数会在Promise状态变更为Rejected时被触发。
  2. .then(null, (err) => {})的第二个参数,也是在Promise状态变更为Rejected时被触发。故其实.catch()和 .then()的reject回调函数本质上是一样的,只是写法不一样。但我们一般更倾向于使用.catch()而不使用.then的reject回调。原因后面会讲
  3. 代码抛出错误和reject()函数执行都会让Promise对象的状态转变为Rejected,故两种情况都会触发catch()的回调执行或者then()的reject回调执行。 所以,reject()的本质,其实就是抛出一个错误
  4. .catch()的回调函数以及.then的reject回调一样,执行时默认都会返回一个状态为Resolved的Promise对象(也就是 return Promise.resolve())
  5. .catch()和.then()一样,也可以写多个,也支持链式操作,原因就是上面的第三点
  6. 抛出的错误一旦被catch捕获,便不会再向外传播,只有再次向外抛出错误,才会继续被后面的catch所捕获。故错误具有冒泡性质,会一步一步向外传播,直到被catch捕获

1、我们先看第一点:

var getData = function() {
 return new Promise(function(resolve, reject) {
  reject(123)
 });
};
getData().then((res) => {
 console.log('成功')
}).catch((err) => {
 console.log('捕捉到错误')
 console.log(err)
})

// 捕捉到错误
// 123

毫无疑问,reject(123)抛出一个错误,catch的回调捕捉到错误,并输出

2、再看第二点:

var getData = function() {
 return new Promise(function(resolve, reject) {
  reject(123)
 });
};
getData().then((res) => {
 console.log('成功')
}, (err) => {
	console.log('捕捉到一个错误')
	console.log(err)
})

// 捕捉到错误
// 123

从代码上也可以看出,上面这两种方式是一样的。

现在,我来说说为什么建议使用catch() ,而不推荐使用then()的reject回调呢。看下下面的代码

var getData = function() {
 return new Promise(function(resolve, reject) {
  resolve(123)
 });
};
getData().then((res) => {
 console.log('成功')
 return new Promise((resolve, reject) => {
  reject(new Error('123'))
 })
}, (err) => {
	console.log('捕捉到一个错误')
	console.log(err)
})

// 成功

此时,只输出了成功, 而then的resolve回调中所抛出的错误,并没有被捕捉到

再看下面一段代码

var getData = function() {
 return new Promise(function(resolve, reject) {
  resolve(123)
 });
};
getData().then((res) => {
 console.log('成功')
 return new Promise((resolve, reject) => {
  reject(new Error('123'))
 })
}).catch((err) => {
	console.log('捕捉到一个错误')
	console.log(err)
})

成功
捕捉到一个错误
Error: 123

看,同样的错误,但是使用catch(),可以捕捉到,而使用then()的reject回调,却捕捉不到。

结论:catch()可以通过放到操作链的最底部而捕捉到任意地方(指的是Promise内)的错误。而then()的reject回调,只能捕捉到这个.then()执行之前的错误,当前执行的then的resolve回调内的错误无法捕捉到,后面再执行的代码所抛出的错误也无法捕捉到。并且.catch的写法,代码层面也更为清晰

var getData = function() {
 return new Promise(function(resolve, reject) {
  resolve(123)
 });
};
getData().then((res) => {
 console.log('成功')
 return new Promise((resolve, reject) => {
  reject(new Error('123'))
 })
}, (err) => {
 console.log('第一个错误捕捉')
}).then((res) => {
 console.log('第二个resolve回调')
}, err => {
 console.log('第二个错误捕捉')
})

成功
第二个错误捕捉

如上图中,第一个then的resolve回调中抛出的错误被第二个then中reject回调所捕捉

故 结论:一般情况下,不要去用then的第二个参数,而尽可能的去用.catch()方法去捕捉错误

3、下面我们再看第三点

var getData = function() {
 return new Promise(function(resolve, reject) {
  resolve(x)
 });
};
getData().then((res) => {
 console.log('成功')
}).catch(err => {
 console.log('捕捉到一个错误')
 console.log(err)
 throw new Error('我抛出了一个错误')
}).catch(err => {
 console.log('我也捕捉到了一个错误')
 console.log(err)
})

捕捉到一个错误
ReferenceError: x is not defined
我也捕捉到了一个错误
Error: 我抛出了一个错误

上面代码可以看出,不是只有reject()执行了才会抛出一个错误,x未定义,系统会自动抛出一个错误,throw new Error是我们自己手动抛出一个错误。而这些都会使得Promise对象的状态变更为Rejected,从而触发catch。
同时上面的代码我们还可以看出我们上面写的第六点,错误会冒泡式向外传播,当被catch之后,便不会再进行传播了。直到再次抛出错误。上面代码中,第一个错误被第一个catch捕获后,原本第二个catch是不会再走的,但因为在第一个catch中又抛出了一个错误,才导致了第二个catch的执行。

4、下面我们再看第四点(catch()的回调函数也会返回一个状态是Resolved的Promise实例)
其实这一点,我们从上面那张图中也是可以看出来的,第一个catch()的回调原本是要返回了一个Resolved状态的Promise,但是因为throw了一个错误,导致这个Promise实例状态变更为Rejected并返回,而变成成Rejected变触发了第二个catch的回调执行

我们看下下面的代码,再次验证下

var getData = function() {
 return new Promise(function(resolve, reject) {
  resolve(x)
 });
};
getData().then((res) => {
 console.log('成功')
}).catch(err => {
 console.log('捕捉到一个错误')
 console.log(err)
}).then((res) => {
 console.log('我是第二个then')
})

捕捉到一个错误
ReferenceError: x is not defined
我是第二个then

上面代码可以看出,catch的回调执行后,后面的then依然被执行了,为什么,就是因为catch的回调执行后默认返回了一个Resolved状态的Promise实例(return Promise.resolve())

第五点,第六点我们已经验证过了。不再多说。

实现简单的axios

axios我们比较常用,大家应该都发现了,axios的使用方式,和Promise好像是一样的,

axios({
 url:'http://www.baidu.com',
 method: 'post',
 data: {}
}).then((res) => {
 console.log(res)
}).catch((err) => {
 console.log(err)
})

没错。axios就是一个Promise实例。他是一个用Promise来封装的一个XMLHttpRequest
下面我们也来实现一个简单的axios

function MyAxios(option) {
 return new Promise((resolve, reject) => {
  const http = new XMLHttpRequest()
  http.open(option.method, option.url);
  http.responseType = "json";
  http.setRequestHeader("Accept", "application/json");
  http.onreadystatechange = myHandler;
  http.send();

  function myHandler() {
   if (this.readyState !== 4) {
    return;
   }
   if (this.status === 200) {
    resolve(this.response);
   } else {
    reject(new Error(this.statusText));
   }
  }
 })
}
MyAxios({
 url:'http://www.baidu.com',
 method: 'post'
}).then((res) => {
 console.log(res)
}).catch((err) => {
 console.log(err)
})

Promise.all, Promise.race 以及两者的区别

1、Promise.all

Promise.all()可以并行执行多个Promise(), 并返回一个新的Promise实例

var p = Promise.all([p1, p2, p3]); // p1,p2,p3为3个Promise实例

Promise.all()的参数不一定是数组,只要具有Iterator接口的数据都可以(Iterator是一个遍历器,我这里就不做过多介绍,感兴趣的可以自己去官网看看)。但是参数遍历后返回的成员必须必须是Promise对象(如上面的,p1,p2,p3都必须是Promise对象,如果不是,则会先调用Promise.resolve(p1)将他转化为Promise实例)

那么,Promise.all()返回的Promise实例的状态是如何定义的。

  • 只有参数的各个成员(p1,p2,p3)状态都变成Resolved,p的状态才会变成Resolved,
  • 参数的各个成员中,有任意一个状态变成Rejected, p的状态都会立刻变成Rejected
function getData (data) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   if (data === 6) {
    reject(new Error('请求发生错误了'))
   } else {
    resolve(data)
   }
  }, data * 500)
 })
}
const promises = [1,3,5,7].map((item) => {
 return getData(item)
})
Promise.all(promises)
.then((res) => {
 console.log('请求成功')
 console.log(res)
}).catch((err) => {
 console.log('请求失败')
 console.log(err)
})

// 3.5s后输出
请求成功
[ 1, 3, 5, 7 ]

如上图, 最后一个成员(上图中7返回的promise实例)的状态是在3.5s后才变更为Resolved,故.then()的resolve回调在3.5s后才执行

function getData (data) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   if (data === 6) {
    reject(new Error('请求发生错误了'))
   } else {
    resolve(data)
   }
  }, data * 500)
 })
}
const promises = [2,4,6,8].map((item) => {
 return getData(item)
})
Promise.all(promises)
.then((res) => {
 console.log('请求成功')
 console.log(res)
}).catch((err) => {
 console.log('请求失败')
 console.log(err)
})

// 3s后输出
请求失败
Error: 请求发生错误了

上图可以看出,当我们改用 2,4,6,8去得到promise成员时,第3s得时候 发生了错误,此时,Promise.all()返回得Promise实例得状态立刻变更为Rejected,catch()的回调立即触发。故输出错误

2、Promise.race()

Promise.race()和Promise.all()的作用是一样的,都是并发处理多个Promise实例,并返回一个新的实例。
而区别在于,两者返回的新的Promise实例的状态改变的时机不同。

Promise.all是 所有Promise子成员状态都变为Resolved, 新的Promise实例状态才会变成Resolved。中途如果有任何一个子成员状态变成了Rejected,新的Promise实例的状态就会立刻变为Rejected

Promise.race是 只要子成员中,有任何一个的状态发生了变化(不管是变成Resolved还是Rejected),那么返回的新的Promise实例的状态也会立刻发生变化,而变化的状态就是那个子成员所变化的状态。

function getData (data) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   if (data === 6) {
    reject(new Error('请求发生错误了'))
   } else {
    resolve(data)
   }
  }, data * 500)
 })
}
const promises = [2,4,6,8].map((item) => {
 return getData(item)
})
Promise.race(promises)
.then((res) => {
 console.log('请求成功')
 console.log(res)
}).catch((err) => {
 console.log('请求失败')
 console.log(err)
})

// 1s后输出
请求成功
2

上图可以看出,1s后 第一个子成员状态变更为Resolved,那么返回的新Promise实例状态也立马变更为Resolved,故1s后.then()的resolve回调执行。输出请求成功.

最后,我们来说一说前面用到了的Promise.resolve()吧

Promise.resolve和Promise.reject

Promise.resolve()

前面我们说到过 Promise.resolve可以返回一个状态是Resolved的Promise对象。没错,其实它等同于

new Promise((resolve, reject) => {
 resolve()
})

当Promise.resolve()有参数时,会返回一个Promise对象的同时,将参数做作为then()resolve回调的参数返回(当参数是thenable对象除外,后面会将)。主要有以下几种情况

1、参数是一个Promise对象时

将会直接返回这个参数,不做任何更改

2、参数是thenable对象时,(即,存在.then()方法的对象),如下

let obj= {
 then: function(resolve, reject) {
 resolve('我是thenable对象');
 }
};

此时,Promise.resolve(obj) 会返回一个Promise对象,并且调用obj的then()方法,哎,这里注意了,这个.then()并不是 新Promise对象的.then() , obj的then()会立即执行,可不代表 新的Promise对象的then() 的回调也会执行, 还记得吗,我们前面说的Promise对象的then()的回调执行的条件是这个Promise对象的状态发生变化了才会执行。

let obj= {
 then: function(resolve, reject) {
  console.log(123)
 }
};

let p1 = Promise.resolve(obj);
p1.then(function(value) {
 console.log('成功')
 console.log(value); // 42
});
// 输出
123

从上图可以看出来,立即执行了obj.then(),但Promise的then的回调并没有被执行

3、参数不是对象,或者说是没有.then方法的对象

会返回一个Promise实例,并将参数作为.then()的resolve回调的参数返回

如,Promise.resolve(‘123') 等价于

new Promise((resolve, reject) => {
 resolve('123')
})

4、不带参数,即Promise.resolve(),也就是我们前面说的。

返回了一个Resolved状态的Promise对象,但是.then()的resolve回调没有参数。

new Promise((resolve, reject) => {
 resolve()
}).then((res) => {
	console.log(res)
})
// 输出
undefined

Promise.resolve()

Promise.reject() 也是返回一个Promise对象,只是这个对象的状态是Rejected
至于参数的用法和Promise.resolve()完全一样,唯一的区别是没有thenable参数一说,也就是说有参数时,参数不论哪种情况,都会被当做catch()的回调参数返回。也就是说参数没有前面1,2,3种的区别。大家可以去试试,我就不过多说明了。

总结

到此这篇关于ES6学习教程之Promise用法详解的文章就介绍到这了,更多相关ES6之Promise用法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • ES6基础之 Promise 对象用法实例详解

    本文实例讲述了ES6基础之 Promise 对象用法.分享给大家供大家参考,具体如下: Promise 对象 1.Promise对象是ES6对异步编程的一种解决方案,它有以下两个特点: Promise对象代表一个异步操作,它只有三种状态:Pending(进行中).Resolved(已完成,又称 Fulfilled)和Rejected(已失败),并且该状态不会受外界的影响 Promise对象的状态改变,只有两种可能:从 Pending 变为 Resolved 或者从 Pending 变为 Reje

  • ES6 Promise对象的含义和基本用法分析

    本文实例讲述了ES6 Promise对象的含义和基本用法.分享给大家供大家参考,具体如下: 1.Promise的含义 Promise是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理更强大. 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件 (通常是一个异步操作)的结果.从语法上说,Promise是一个对象,从它可以获取异步操作的消息. Promise对象有以下2个特点: 1.对象的状态不受外界影响.Promise对象代表一个异步操作,有三种状态:Pend

  • es6中Promise 对象基本功能与用法实例分析

    本文实例讲述了es6中Promise 对象基本功能与用法.分享给大家供大家参考,具体如下: Promise 是异步编程的一种解决方案,解决--回调函数和事件 ES6 规定,Promise对象是一个构造函数,用来生成Promise实例. 下面代码创造了一个Promise实例. 基本用法 ES6 规定,Promise对象是一个构造函数,用来生成Promise实例. const promise = new Promise(function(resolve, reject) { //resolve (d

  • ES6关于Promise的用法详解

    Node的产生,大大推动了Javascript这门语言在服务端的发展,使得前端人员可以以很低的门槛转向后端开发. 当然,这并不代表迸发成了全栈.全栈的技能很集中,绝不仅仅是前端会写一些HTML和一些交互,后台熟悉数据库的增删查改. 想必接触过Node的人都知道,Node是以异步(Async)回调著称的,其异步性提高了程序的执行效率,但同时也减少了程序的可读性.如果我们有几个异步操作,并且后一个操作需要前一个操作返回的数据才能执行,这样按照Node的一般执行规律,要实现有序的异步操作,通常是一层加

  • ES6 Promise对象概念与用法分析

    本文实例讲述了ES6 Promise对象概念与用法.分享给大家供大家参考,具体如下: 1.Promise概念 Promise 对象有三种状态: ① Fulfilled 可以理解为成功的状态 ② Rejected 可以理解为失败的状态 ③ Pending 既不是 Fulfilld 也不是 Rejected 的状态,可以理解为 Promise 对象实例创建时候的初始状态 2.三个重要方法 在 Promise 对象当中有三个重要方法----resolve, reject和then. resolve 方

  • ES6中异步对象Promise用法详解

    本文实例讲述了ES6中异步对象Promise用法.分享给大家供大家参考,具体如下: 回忆一下ES5中的怎么使用异步方法 // es5中的异步回调 let ajax = function(callback){ console.log('执行') // 执行 setTimeout(() => { callback&&callback.call(); }, 1000) }; ajax(function(){ console.log('hello') // 1s后打印hello }); 使用

  • 深入解析ES6中的promise

    ES6中的promise对象很早就听说过,据说是为了解决我们使用回调产生回调地狱的问题.今天下午既然有这么想学的欲望,就来看一看吧,当然参考的还是阮一峰老师的教程. 第一部分:什么是Promise 看本文的最后一个例子,迅速理解. Promise是ES6中的一个内置的对象(实际上是一个构造函数,通过这个构造函数我们可以创建一个Promise对象),它是为了解决异步问题的.Promise的英文意思是承诺. Promise的特点如下: •Promise有三种状态:Pending(进行中).Resol

  • ES6的异步操作之promise用法和async函数的具体使用

    promise 基本用法 Promise 对象是一个构造函数,用来生成 Promise 实例.Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject. resolve 函数的作用是,在异步操作成功时调用(Promise 对象的状态从 pending 变为 fulfilled),并将异步操作的结果,作为参数传递出去. reject 函数的作用是,在异步操作失败时调用(Promise对象的状态从 pending 变为 rejected),并将异步操作报

  • ES6 Promise对象概念及用法实例详解

    本文实例讲述了ES6 Promise对象概念及用法.分享给大家供大家参考,具体如下: 参考文章:ECMAScript 6 入门 一. Promise是什么 Promise是异步编程的一种解决方案,它是一个容器,里面保存着某个未来才会结束的事件的结果.它有三种状态,只有异步操作的结果才能决定当前的状态,不受外界因素的影响.而一旦状态改变,就不会再变,也就是状态凝固了(resolved),任何时候都可以得到这个结果. Promise的缺点: 1. 无法取消Promise,一旦新建它就会立即执行,无法

  • ES6学习教程之Promise用法详解

    前言 promise用了这么多年了,一直也没有系统整理过.今天整理整理promise的相关东西,感兴趣的可以一起看一看.我尽量用更容易理解的语言来剖析一下promise 我准备分两篇文章来说明一下promise 一篇来理解和使用promise(本篇) 另一篇来从promise使用功能的角度来剖析下promise的源码(下一篇) 1.什么是Promise 我的理解是:实现让我们用同步的方式去写异步代码的一种技术.是异步解决方案的一种. 他可以将多个异步操作进行队列化,让它们可以按照我们的想法去顺序

  • Zend Framework教程之Autoloading用法详解

    本文实例讲述了Zend Framework教程之Autoloading用法.分享给大家供大家参考,具体如下: 一.概述 自动加载是一种机制,无需依赖手动编写PHP代码.参考»PHP手册自动加载,一旦自动加载器被定义,你试图使用一个没有定义的类或接口的情况下,它会自动被调用. 使用自动加载,在项目中你不必担心类的存放位置.定义一个良好定义的自动加载器,您不需要考虑一个类文件相对于当前类文件的位置,您只需使用类,自动加载器将自动查找文件. 此外,自动加载,确保只加载一次,提升了性能 -所以可以用它替

  • Laravel学习教程之View模块详解

    前言 本文主要是给大家介绍了关于Laravel中View模块的相关资料,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 本文是基于Laravel 5.4版本的路由模块代码进行分析书写: 文件结构 View模块的文件格局及功能如下图所示: 视图化呈现时的大概流程: 1.通过view()方法的调用,开始视图的呈现: 2.首先,查找视图文件: (1)依次遍历路径,如果文件名带命名空间(也就是::之前的部分),则采用命名空间对应注册的路径数组,否则采用全局路径数组(在Illuminat

  • Zend Framework教程之Zend_Db_Table用法详解

    本文实例讲述了Zend_Db_Table用法.分享给大家供大家参考,具体如下: 1. 简介 Zend_Db_Table 是Zend Framework的表模块.它通过zend_db_adapter连接到 数据库,为数据库模式检查表对象,并对该表进行操作和查询. 2. 开始 首先需要为抽象类zend_db_table(ares注:该类为抽象类,所以不能直接实例 化,只能先继承该类,然后实例化子类)设定一个默认对数据库adapter;除非你 指定其他类型数据库adapter,否则,所有的zend_d

  • ES6的Promise用法详解

    目录 什么是Promise reject的用法 catch的用法 all的用法 race的用法 什么是Promise Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all.reject.resolve这几个方法,原型上有then.catch等方法.(ps:什么是原型:https://www.jb51.net/article/231967.htm) Promise对象有以下两个特点. (1)对象的状态不受外界影响.Promise对象代表一个异步操作,有三种状态:pendi

  • ES6新增数据结构WeakSet的用法详解

    WeakSet和Set类似,同样是元素不重复的集合,它们的区别是WeakSet内的元素必须是对象,不能是其它类型. 特性: 1.元素必须是对象. 添加一个number类型的元素. const ws = new WeakSet() ws.add(1) 结果是报类型错误. TypeError: Invalid value used in weak set 添加一个对象. const ws = new WeakSet() var a = {p1:'1', p2:'2'} ws.add(a) conso

  • 基于Android studio3.6的JNI教程之opencv实例详解

    基本环境: Android studio3.6 NDK:r14b(尽量使用该版本) Opencv3.4.1 android sdk (1)新建工程OpenCVDemo,选择,一定要选择Native c++类型,最后要选c++14支持. (2)File->Project Structure->SDK Location,设置这3个路径,NDK选择r14b. (3)任意找一张图片,复制到res/drawable. (4)修改布局文件res/layout/ activity_main.xml <

  • 基于Android studio3.6的JNI教程之helloworld思路详解

    jdk环境变量配置: path中增加下面2个路径,也就是android studio的路径,android有自带的jdk. E:\Android\Android Studio\jre\bin E:\Android\Android Studio\bin 新建工程: 一定要选择Native c++类型,最后要选c++11支持. SDK设置: File->Settings File->Project Structure 首先确定工程的目录结构,然后尝试运行一下工程,使用模拟器,确保工程没问题, 在M

  • Python基础教程之pytest参数化详解

    目录 前言 源代码分析 装饰测试类 装饰测试函数 单个数据 一组数据 组合数据 标记用例 嵌套字典 增加测试结果可读性 总结 前言 上篇博文介绍过,pytest是目前比较成熟功能齐全的测试框架,使用率肯定也不断攀升.在实际 工作中,许多测试用例都是类似的重复,一个个写最后代码会显得很冗余.这里,我们来了解一下 @pytest.mark.parametrize装饰器,可以很好的解决上述问题. 源代码分析 def parametrize(self,argnames, argvalues, indir

随机推荐