赞
踩
Promise
对象代表一个异步
操作,有三种状态,只有异步操作的结果
,可以决定当前是哪一种状态。
这里只是new了一个对象,并没有调用它,我们传进去的函数就已经执行了
new Promise((resolve, reject) => {
// 异步工作处理
...
// 异步工作执行完之后
resolve(result) // ——如果成功完成,并返回结果result;
reject(error) // ——如果执行是失败并产生error;
})
我们用Promise的时候一般是包在一个函数中,在需要的时候去运行这个函数
<div onClick={promiseClick}>开始异步请求</div>
const promiseClick =()=>{
console.log('点击方法被调用')
let p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('执行完成Promise');
resolve('要返回的数据可以任何数据例如接口返回数据');
}, 2000);
});
return p
}
promise.then(function(result),function(error))
let promise = new Promise((resolve, reject) => { // 异步工作处理 ... // 异步工作执行完之后 resolve(result) // ——如果成功完成,并返回结果result; reject(error) // ——如果执行是失败并产生error; }) promise .then( (result) => { console.log('成功执行,resolve(result)') }, (error) => { console.log('失败执行,reject(error)') } ) .catch( // 区别:还可以获取到then的第一个函数的报错 (err)=>{console.log('等同于then的第二个error函数')} )
function myReadFile(path) { return new Promise((resolve, reject) => { fs.readFile(path, (err, data) => { if (err) reject(err) console.log(data.toString()) resolve(data) }) }) } myReadFile('1.txt') // 返回Promise .then(data => { return myReadFile('2.txt') }) // 再次调用myReadFile,返回Promise .then(data => { return myReadFile('3.txt') }) // 依次类推 .then(data => { return myReadFile('4.txt') }) .then(data => { return myReadFile('5.txt') }) .then(data => { return myReadFile('6.txt') }) .then(data => { return myReadFile('7.txt') }) .then(data => { return myReadFile('8.txt') }) .then(data => { return myReadFile('9.txt') }) .then(data => { return myReadFile('10.txt') })
注意:
promise.then()的返回值
其实是一个Promise对象
,这个新Promise的决议是等到then方法传入的回调函数有返回值时, 进行决议(要有return 数据)。- 当promise进行链式调用时promise.then().then(),第二个then的res其实是第一个then方法里的return的数据,包装成Promise。参考下面demo,理解链式调用
- catch()只需要一个就可以了,抛出异常可以用
throw new Error("第三个Promise的异常error")
const promise = new Promise((resolve, reject) => { resolve("aaaaaaa") // reject() }) // 1.then方法是返回一个新的Promise, 这个新Promise的决议是等到then方法传入的回调函数有返回值时, 进行决议 // Promise本身就是支持链式调用 // then方法是返回一个新的Promise, 链式中的then是在等待这个新的Promise有决议之后执行的 promise.then(res => { console.log("第一个then方法:", res) // 打印 "aaaaaaa" return "bbbbbbbb" }).then(res => { console.log("第二个then方法:", res) // 打印 "bbbbbbbb" return "cccccccc" }).then(res => { console.log("第三个then方法:", res) // 打印 "cccccccc" }).catch(err => { console.log("catch回调被执行:", err) })
假设现在有A、B两个任务需要处理,使用并行、同步和异步的处理方式会分别采用如下图所示的执行方式:
Promise.all:多个异步请求,如果有一个错误,会在catch里返回错误结果,但多个请求仍然会发出请求。
应用场景:基本是在多个请求中【获取数据】时才会用到,直接提交的接口不要用Promise.all的
参数的执行顺序
和结果的返回顺序
执行顺序:谁执行的快谁先打印结果。
返回顺序:按照promise的添加顺序返回
function promise1 () { return new Promise(resolve => { setTimeout(() => { resolve('1'); }, 10000); }) } function promise2 () { return new Promise(resolve => { setTimeout(() => { resolve('2'); }, 1000); }) } Promise.all([promise1(), promise2()]).then(function(results){ console.log(results); // results:['1', '2'] });
async是一个加在函数前的修饰符,被async定义的函数会默认返回一个Promise对象resolve的值
async function fun0(){
return new Promise(function(resolve,reject){
resolve('Promise对象')
})
}
console.log(fun0()); // Promise {<fulfilled>: 'Promise对象'}
fun0().then(res=>console.log(res)); // 通过then获取结果:Promise对象
async function fun0(){
return '常规变量';
}
console.log(fun0()); // Promise {<fulfilled>: '常规变量'}
fun0().then(res=>console.log(res)); // 通过then获取结果:常规变量
underfind
async function fun0(){}
console.log(fun0()); // Promise {<fulfilled>: undefined}
fun0().then(res=>console.log(res)); // 通过then获取结果:undefined
await 也是一个修饰符,只能放在async定义的函数内。可以理解为等待。
它会阻塞后面的代码,等Promise中返回的内容(resolve或reject的参数),且取到值后语句才会往下执行
async function fun(){
let a = await 1;
let b = await new Promise((resolve,reject)=>{
setTimeout(function(){
resolve('setTimeout')
},3000)
})
let c = await function(){
return 'function'
}()
console.log(a,b,c)
}
fun(); // 3秒后输出: 1 "setTimeout" "function"
把这个非promise的东西当做await表达式的结果。
(相当于没有await)
function log(time){ // 普通的异步函数 setTimeout(function(){ console.log(time); },time) } async function fun(){ let a = await log(1000); // 按照异步函数的处理事件快慢决定打印殊勋 let b = await log(3000); let c = log(2000); console.log(a,b,c); // 先执行它,上面是三个都是异步,所以开始abc都是undefined } fun(); // 立即输出 undefined undefined undefined // 1秒后输出 1000 // 2秒后输出 2000 // 3秒后输出 3000
// Promise 写法 function p(){ return new Promise((resolve,reject)=>{ setTimeout(()=>{resolve('Promise写法')},1000) }) } p().then(res=>{console.log(res)}) // async/await 写法 function a(){ return new Promise((resolve,reject)=>{ setTimeout(()=>{resolve('async/await写法')},1000) }) } async function fn() { const res = await a() console.log(res); } fn()
// Promise 写法 function p(time){ return new Promise((resolve,reject)=>{ setTimeout(()=>{ console.log('Promise写法' + time); resolve('Promise返回数据')},time) }) } p(1000) .then(res=>{return p(2000)}) .then(res=>{return p(3000)}) .then(res=>{return p(4000)}) .then(res=>{return p(5000)}) // async/await 写法 function a(time){ return new Promise((resolve,reject)=>{ setTimeout(()=>{ console.log('async/await写法' + time); resolve('async/await返回数据')},time) }) } async function fn() { const res1 = await a(1000) const res2 = await a(2000) const res3 = await a(3000) const res4 = await a(4000) const res5 = await a(5000) } fn()
前两步骤都是一样的,promise直接执行,async/await 通过第三方函数执行
- fn函数要
return
一个promise对象
:[return new Promise()]- 在promise对象中进行
异步处理
,通过resolve/reject
出去结果/错误- 调用fn函数,通过
then
方法获取结果/错误
- fn1函数要
return
一个promise对象
:[return new Promise()]- 在promise对象中进行
异步处理
,通过resolve/reject
出去结果/错误- 定义一个
async
fn2函数,函数里await
fn1函数- 通过
变量接收
fn1函数的结果调用
(执行)fn2 函数
除了主任务栈,事件循环中并非只维护着一个队列,事实上是有两个队列:
ajax
、setTimeout
、setInterval
、DOM监听
、UI Rendering
等Promise的then回调
、 Mutation Observer API
、queueMicrotask()
等注意:
- 在
async/await
中,视为同步代码(await上面和右边),在主任务栈里执行。但await
前后会有区分,看第2条说明- 执行到
async
函数时,await上面和右边的内容会在主任务栈里执行,await右边和下面的内容,会在Promise有返回结果时,加入到微任务中开始执行- Promise对象里的代码,是同步执行的,只有
then
回调是微任务。- 调用
then
之前,会先将Promise内部的代码执行完才会执行到then。或者说必须是执行到了resolve()
才可以。await
是会阻塞后面的代码执行,必须等到promise
的结果resolve()
(类似于第4条then的执行顺序)
主任务栈, 宏任务队列,微任务队列,他们三个的执行顺序:
<script> function foo() { console.log("foo function1") throw new Error("我是错误信息") console.log("foo function2") console.log("foo function3") console.log("foo function4") } function test() { // 自己捕获了异常的话, 那么异常就不会传递给浏览器, 那么后续的代码可以正常执行 try { foo() console.log("try后续的代码") } catch(error) { console.log("catch中的代码") // console.log(error) } finally { console.log("finally代码") } } test() console.log("--------") </script>
注意:
throw
抛出异常信息new Error("自定义错误信息")
生成异常信息try/catch/finally
接收异常
防抖:只有在某个时间内,没有再次触发某个函数时,才真正的调用这个函数;
(等待最后一次才进行函数调用)
function debounce(fn, delay){
let timerId = null
return function(){
const context = this
//如果接到订单就再等3分钟
if(timerId){window.clearTimeout(timerId)}
//3分钟没有接到订单就直接配送
timerId = setTimeout(()=>{
fn.apply(context, arguments)
timerId = null
},delay)
}
}
节流:在某个时间内(比如500ms),某个函数只能被触发一次;
(按照一定的频率进行调用)
function throttle(fn, delay){
// 设置一个触发开关
let canUse = true
return function(){
//如果为true,就触发技能,否则就不能触发
if(canUse){
fn.apply(this, arguments)
//触发技能后,关闭开关
canUse = false
//在3秒后打开开关
setTimeout(()=>{canUse = true}, delay)
}
}
}
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。