首页 专题 H5案例 前端导航 UI框架

避免回调地狱和长链式then,快速实现具有继发关系的请求

作者:TG 日期: 2017-11-01 字数: 6560 阅读: 4454
这篇文章不是为了介绍回调地狱也不是介绍Promise,而是介绍如何实现具有继发关系的多个请求。

何为继发关系?

比如有三个请求A、B、C,B要等待A请求的结果再发起请求,C要等待B请求的结果再发起请求,也就是A - B - C有所关联,这就是继发关系。

问题的转移

一直以来,回调地狱是大问题,随着ES6的完成,Promise出现了,解决了回调地狱,但在请求具有继发关系的请求时,又出现了另一个问题,会出现长链式then。

async/await

现在我们可以使用ES7中的async/await了。

async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

Async用来定义异步函数

语法:async function someName(){}

Await用来暂停异步函数的执行

语法:const step = async function someName(){...}

更多关于async函数:http://es6.ruanyifeng.com/#docs/async

下面直接上例子。

如果支持async,比如Typescript/Node 7.6+中,可以这样快速实现:

asyncRequest(requestArrs: any, context: any) {   

  const values = [];   

  let num = 0;   

  const req = async () => {  

      for (const request of requestArrs) { 

        try {

          values[num] = await context[request](values[num - 1] || null); 

        } catch(err) {

           console.error(err);

        }

        num++;   

      }   

      return values[values.length - 1];  

  };   

  return req;   

}   


const steps = {   

  step1(res) {   

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

      setTimeout(() => {   

        resolve(321);   

      }, 1000);   

    });   

  },   

  step2(res) {   

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

      setTimeout(() => {   

        resolve(123 + res);   

       }, 500);

    });   

   }   

};  


asyncRequest(['step1', 'step2'], steps)().then(res => {   

   console.log(res);  

});

asyncRequest函数的第一个参数是一个字符串数组,包含要执行的函数名称;第二个参数是这些函数的上下文,它返回一个异步函数,也就是上面的req函数,异步函数最终返回的是一个promise,所以你可以使用then。 在Node端如何还未支持async,但要支持ES6,可以借助Generator函数co库

const co = require('co');   


const asyncRequest = function(requestArrs, context) {   

  const values = [];   

  let num = 0;   

  const req = function* () {    

      for (const request of requestArrs) { 

        try {

          values[num] = yield context[request](values[num - 1] || null); 

        } catch(err) {

           console.error(err);

        }

        num++;   

      }   

      return values[values.length - 1];

  };   

  return req;  

}    


const steps = {   

  step1(res) {   

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

      setTimeout(() => {   

        resolve(321);   

      }, 1000);   

    });   

  },   

  step2(res) {   

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

      setTimeout(() => {   

        resolve(123 + res);   

      }, 500);   

    });   

  }   

};   

const async = asyncRequest(['step1', 'step2'], steps);   

co(async).then(res => {   

  console.log(res)   

});

就是这么简单,只需定义多个请求函数,就可以完成继发关系的请求,再也不用多层嵌套或长链式then了。


如果有疑问,欢迎在下方评论留言!


目录