记录promise 和 async那些事

Promise是一个对象,可以获取异步操作的消息。
一、Promise特点
对象的状态不受外界影响,一旦状态改变,就不会再变)(1)异步操作有三个状态(pending(进行中)、resolved(已成功)和rejected(已失败)):只有异步操作的结果可以决定当前是哪一种状态。任何其他操作都无法改变这个状态。
(2)只有两种状态切换:进行中=> 已成功,进行中=> 已失败。状态切换就会凝固,不会再改变。也就是说切换状态只会发生其中一种,不会同时存在两种都有的场景,再对Promise对象添加回调函数也会立即得到这个结果。所以:Promise就可以将异步操作以同步操作的流程表达出来。
Promise缺点
(1)一旦新建Promise就会立即执行,无法中途取消。
(2)如果不设置回调函数,Promise内部跑出的错误或者数据无法反应到外部。二、Promise基本用法
ES6规定,Promise对象是一个构造函数,用来生成Promise实例。
Promise实例生成后,可以用then方法分别指定resolve状态和rejected状态的回调函数resolve函数的作用是:(即从pending变为resolved)reject函数的作用是:(即从pending变为rejected)

function timeout(ms) {
    return new Promise((resolve, reject) => {
        console.log('promise创建立即执行')
        setTimeout(reject, ms, 'do somthing')//setTimeout 传参
        //setTimeout(resolve, ms, 'do somthing')    })
}
timeout(100).then((value) => {
    console.log('1',value)//do somthing
}).catch((Error) => {
	console.log('2',Error)
})
console.log('同步')
输出顺序:
promise创建立即执行
同步
do somthing

timeout函数触发生成返回Promise实例,此时是新建Promise就会立即执行,然后点then来指定状态的回调函数,将在当前脚本所有同步任务执行完成后才会执行,所以resolve方法最后执行。
Promise.prototype.then方法指定状态的回调函数,返回是一个新的Promise实例(注意,不是原来那个Promise实例),因此可以采用链式写法,即then方法后面再调用另一个then方法。
Promise实例具有then方法,也就是说then方法时定义在原型对象上的。Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。错误回调具有冒泡性质,会一直向后传递,直到被捕获为止。永久保持该状态,不会再变了(也就是说错误回调只会执行一次,后续不再触发)。同时错误能恢复(promise 会认为你已经恢复了该错误,promise 的状态会转变为 resolved)

timeout(100).then((value) => {
    console.log('1',value)//do somthing
}).catch((Error) => {
    console.log('2',Error)
})
等价于
timeout(100).then((value) => {
    console.log('1',value)//do somthing
}).then(null,Error =>{
	console.log('2', Error)
})

Promise.all(iterable) 方法返回一个 Promise 实例,返回顺序和数组顺序一致,不存在时间快慢之分,存在状态之分。无论怎么样输出都是p1优先p2。但是只要有一个promise 返回rejected,那么此实例回调失败(reject)。处理多个异步处理时非常有用。

Promise.all([p1, p2]).then((result) => {
    console.log(result)  
  }).catch((error) => {
    console.log(error)
  })

Promise.race(iterable) 方法返回一个 promise。赛跑,也就是谁快就执行谁,有时间快慢之分,没有状态之分。返回的 promise就会解决或拒绝。

Promise.race([p1, p2, p3]).then((result) => {
    console.log(result)  
  }).catch((error) => {
    console.log(error)
  })

Promise.race()实现接口超时限制

 Promise.race([
    axios.get(url),  //调用后端接口
    new Promise(function(resolve,reject){  //5秒后执行,如果后端接口没有返回,则直接返回error
        setTimeout(()=>{reject(new Error('request timeout')),5000})
    })
    .then((response)=>{
        //成功返回后处理的逻辑
    })
])

Promise resolve()用法Promise.resolve(‘foo’)
// 等价于
new Promise(resolve => resolve(‘foo’))
Promise reject()用法。Promise.reject(‘foo’)
// 等价于
new Promise(reject => reject(‘foo’))

几个注意点
(1)then() 返回一个 forked Promise(分叉的 Promise) // 第一种:如果 func1 抛出一个异常,func2 依然能执行

var p = new Promise(/*...*/);
p.then(func1);
p.then(func2);

// 第二种:如果 func1 中抛出异常,这个 promise 被 rejected了,结果 func2 被跳过不执行了

var p = new Promise(/*...*/);
p.then(func1)
 .then(func2);

(2)只能捕获来自上一级的异常 同级中的错误回调只有在 promise 被 rejected 或者 promise 自身抛出一个异常时才会被执行(throw new Error(“uhoh”))。resolved状态A1抛出异常B2能捕获到。如果是promise 被 rejected。那么A2能触发。同时错误能被恢复 B1也会触发只是返回undefined。

function timeout(ms) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, ms, 'do somthing')
        //setTimeout(reject, ms, 'do somthing')
    })
}
timeout(100).then((value) => { 
	throw new Error("uhoh"); // A1
},(error) =>{
	console.log('2', error) // 同级A2
}).then((value)=>{
	console.log('3', value) // B1
},(Error) => {
	console.log('4',Error) // 捕获来自上一级异常B2
})

(3)错误能被恢复 没有重新抛出错误,promise 会认为你已经恢复了该错误,promise 的状态会转变为 resolvedPromise 可被视为洋葱的皮层,每一次调用 then 都会被添加一层皮层,每一个皮层表示一个能被处理的状态,在皮层被处理之后,promise 会认为已经修复了错误,并准备进入下一个皮层。

function timeout(ms) {
    return new Promise((resolve, reject) => {
       setTimeout(reject, ms, '1错误回调')
    })
}
timeout(100).then((value) => {
    console.log('1',value)
},(error) =>{
	console.log('2', error) // 抛出错误
}).then((value)=>{
	console.log('3', value)
	return new Promise((resolve, reject) => {
        setTimeout(reject, 100, 'd')
    })
},(Error) => {
	console.log('4',Error)
}).then((value)=>{
	console.log('5', value)
}).catch(error =>{
	console.log('最后', error)
})

(4)resolved 状态的 Promise 不会立即执行、Promise 能被暂停
新建Promise会立即执行,无法中途取消。
resolved 状态的 Promise是: Promise实例生成后.then指定状态的异步回调。Promise 能被暂停同样指的是在.then之后的异步回调中仅仅因为你已经在一个 then() 函数中执行过代码,并不意味着你不能够暂停 promise 去做其他事情。为了暂停当前的 Promise,或者要它等待另一个 Promise完成,只需要简单地在 then() 函数中返回另一个 Promise。
promise参考链接

async是Promise的加强版实际应用
(1)条件语句:async

const makeRequest = async () => {
  const data = await getJSON()
  if (data.needsAnotherRequest) {
    const moreData = await makeAnotherRequest(data);
    console.log(moreData)
    return moreData
  } else {
    console.log(data)
    return data    
  }
}

(2)中间值:调用promise1,使用promise1返回的结果去调用promise2,然后使用两者的结果去调用promise3。

const makeRequest = () => {
  return promise1()
    .then(value1 => {
      return Promise.all([value1, promise2(value1)])
    })
    .then(([value1, value2]) => {      
      return promise3(value1, value2)
    })
}

async中间值

const makeRequest = async () => {
  const value1 = await promise1()
  const value2 = await promise2(value1)
  return promise3(value1, value2)
}

(3)错误处理Async/await使得处理同步+异步错误成为了现实。
我们同样使用try/catch结构,但是在promises的情况下,try/catch难以处理在JSON.parse过程中的问题,原因是这个错误发生在Promise内部。想要处理这种情况下的错误,我们只能再嵌套一层try/catch 。

function getJSON() {
	return new Promise((resolve,reject)=>{
		resolve()
	})
}
const mm = () => {
    try {
    	 getJSON()
        .then(result => {
            const data = JSON.parse(result)
            console.log(data)
        }).catch((err) => {
          console.log('inner',err)
       })
     }
    catch (err) {
        console.log('err', err)
    }
}
mm()

Async/await使得处理同步+异步错误成为了现实

 function getJSON() {
    	return new Promise((resolve,reject)=>{
    		resolve()
    	})
    }
    const mm = async () => {
        try {
        	 const data = JSON.parse(await getJSON())
             console.log('data', data)
         }
        catch (err) {
            console.log('err', err)
        }
    }
    mm()

总之:async/await使得异步代码看起来像同步代码,代码会变得异常简单和直观。
async/await参考链接
督促自我,成长每一步。。。

相关文章

最后的控制台返回空数组.控制台在ids.map函数完成之前运行va...
我正在尝试将rxJava与我已经知道的内容联系起来,特别是来自J...
config.jsconstconfig={base_url_api:"https://douban....
我正在阅读MDN中的javascript,并且遇到了这个谈论承诺并且不...
config.jsconstconfig={base_url_api:"https://douban....
这是我的代码main.cpp:#include<string>#include<...