promise和async await

150 阅读3分钟

需求:在A请求结果返回之后,根据A返回的结果进行下一个B请求,之后的操作依赖于B返回的结果

第一次代码:

getjobFlow (resultData) {
   axios.get(`xxxxxxxxxx/${resultData.Id}`,
      {
        headers: xxxx,
       }).then((res) => {
            let falg = null
            if (res.data.error) {
              falg = false
            } else {
              falg = true
            }
             return falg
      })
    },
    getDefinition () {
      axios.get(`xxxxxxxxx`, {
          headers: xxxxxx,
        })
        .then(async (result) => {
          if (result && result.data && result.data.result) {
            const resultData = result.data.result;
            let res = await this.getjobFlow(resultData)  //undefined
            !resultData.jobId || !res
              ? this.$router.push({ query: { readonly: false } })
              : this.$router.push({ query: { readonly: true } });
              
              ......
            
    },

以上代码,await并不生效,获取的res为undefined

第二次代码:

getjobFlow (resultData) {
   return new Promise((resolve, reject) => {
        axios
          .get(
            `xxxxxxxxxx/${resultData.Id}`,
            {
              headers: xxxx,
            }
          ).then((res) => {
            let falg = null
            if (res.data.error) {
              falg = false
            } else {
              falg = true
            }
            // return falg
            
            resolve(falg)

          }).catch(err => {
            reject(err)
          })
      })


    },
    getDefinition () {
      axios.get(`xxxxxxxxx`, {
          headers: xxxxxx,
        })
        .then(async (result) => {
          if (result && result.data && result.data.error) {
            this.$notify({
              type: "error",
              text: result.data.error,
            });
            Bus.$emit('logErrorMsg', result.data.error, this);
          }
          if (result && result.data && result.data.result) {
            const resultData = result.data.result;
            let res = await this.getjobFlow(resultData)
            !resultData.jobId || !res
              ? this.$router.push({ query: { readonly: false } })
              : this.$router.push({ query: { readonly: true } });
              
            ......
            
            }
          }
        })
        .catch((e) => {
          this.$notify({
            type: "error",
            text: e.message,
          });
        });
    },

此后运行没问题

promise(es6)

通过 new 操作符来实例化。创建新期约时需要传入执行器(executor)函数作为参数。

用法

promise有三个状态: pending(执行中)、success(成功)、rejected(失败):

let a = new Promise((resolve,reject) => {
        //...
        resolve('123')
    });
    
    a.then(result => {
        console.log(result);//123
    });

无论 resolve()和 reject()中的哪个被调用,状态转换都不可撤销。

为避免期约卡在待定状态,可以添加一个定时退出功能。比如,可以通过 setTimeout 设置一个 10 秒钟后无论如何都会拒绝期约的回调:

   let p = new Promise((resolve, reject) => { 
           setTimeout(reject, 10000); // 10 秒后调用 reject()
         });
         
          setTimeout(console.log, 0, p); // Promise <pending>
          setTimeout(console.log, 11000, p); // 11 秒后再检查状态

async/await

  async 表示函数里有异步操作
  await 表示紧跟在后面的表达式需要等待结果。

async

用于声明异步函数。这个关键字可以用在函数声明、函数表达式、箭头函数和方法上,异步函数如果使用 return 关键字返回了值(如果没有 return 则会返回 undefined),这 个值会被 Promise.resolve()包装成一个期约对象。异步函数始终返回期约对象。在函数外部调用这个函数可以得到它返回的期约

async function foo() { 
  console.log(1); 
  return 3;
}
// 给返回的期约添加一个解决处理程序
foo().then(console.log);
console.log(2);
// 1 // 2 // 3

async函数接收到返回的值,发现不是异常或者reject,则判定成功,这里可以return各种数据类型的值,false,NaN,undefined...总之,都是resolve 但是返回如下结果会使async函数判定失败reject

  1. 内部含有直接使用并且未声明的变量或者函数。
  2. 内部抛出一个错误throw new Error或者返回reject状态return Promise.reject('执行失败')
  3. 函数方法执行出错(如:Object使用push())等等...

还有一点,在async里,必须要将结果return回来,不然的话不管是执行reject还是resolved的值都为undefine,建议使用箭头函数。

async function d(){ 
    '这个值接收不到'
}
d().then(success => console.log('成功',success));
//成功 undefined   //没有return
//Promise { <resolved>: undefined }
----------------------------------------------------------- 
async function e(){ 
    return '接收到了'
} 
e().then(success => console.log('成功',success)); 
//成功 接收到了 //Promise { <resolved>: undefined }

await

因为异步函数主要针对不会马上完成的任务,所以自然需要一种暂停和恢复执行的能力。使用 await关键字可以暂停异步函数代码的执行,等待期约解除

会暂停执行异步函数后面的代码,让出 JavaScript 运行时的执行线程。await 关键字同样是尝试“解包”对象的值,然后将这 个值传给表达式,再异步恢复异步函数的执行

很多人以为await会一直等待之后的表达式执行完之后才会继续执行后面的代码,实际上await是一个让出线程的标志await后面的函数会先执行一遍(比如await Fn()的Fn ,并非是下一行代码),然后就会跳出整个async函数来执行后面js栈的代码。等本轮事件循环执行完了之后又会跳回到async函数中等待await****后面表达式的返回值,如果返回值为非promise则继续执行async函数后面的代码,否则将返回的promise放入Promise队列(Promise的Job Queue)

参考来源:

链接:juejin.cn/post/684490…

链接:segmentfault.com/a/119000000…