代码之家  ›  专栏  ›  技术社区  ›  OfirD

等待多个异步函数的承诺链等价物是什么?

  •  0
  • OfirD  · 技术社区  · 7 年前

    我正在研究promsie和async/await的用法。

    我编写了以下代码,它执行以下操作:

    1. 它获取一些数据库的数据(使用knex.js)。
    2. 处理这些数据,
    3. 将处理的数据分配到指定的属性中。

    这三个步骤执行了多次(在下面的代码中,执行了两次),并且始终 await 预计起飞时间:

    async function run() {
       return await getData();
    }
    async function getData() {
        let handledData = {};
        handledData.res1 = await knex.select('column1').from('table1').where('column1', '1')
                                     .then(data => handleData(data))
                                     .catch(handleError);
        handledData.res2 = await knex.select('column1').from('table1').where('column1', '2')
                                     .then(data => handleData(data, handledData))
                                     .catch(handleError);
        return handledData;
    }
    async function handleData(data) {
        let res = [];
        data.forEach(item => {
            res.push(item.column1);
        });
        return res; 
    }
    function handleError (error) {
        console.log(error);
    }
    

    现在,我正在写一个承诺链,相当于 getData 这就是我想到的:

    async function getData() {
        let handledData = {};
        let promise = new Promise(function(resolve, error){ resolve(); });
        promise
        .then(function () {
            return knex.select('column1').from('table1').where('column1', '1')
                        .then(data => handleData(data))
                        .catch(handleError);
        })
        .then(function(handled){
            handledData.res1 = handled;
            return knex.select('column1').from('table1').where('column1', '2')
                        .then(data => handleData(data))
                        .catch(handleError);
        })
        .then(function(handled){
            handledData.res2 = handled;
            return handledData;
        })
        .catch(handleError);
        return promise;
    }
    

    但这不太管用。第一次之后会发生什么 then 返回 等待 里面 run 结束等待,这导致 运行 返回-只有第二个 然后 执行。

    我如何才能让承诺链版本像多等待版本那样工作?

    (请随时指出我对承诺/异步等待的任何误解)

    2 回复  |  直到 7 年前
        1
  •  2
  •   CertainPerformance    7 年前

    如果可能,我建议使用 Promise.all 相反,除了使逻辑更清晰之外,它还将使脚本运行更快:

    const getData = Promise.all([
      knex.select('column1').from('table1').where('column1', '1')
        // Simply pass the function name as a parameter to the `.then`:
        .then(handleData)
        .catch(handleError),
      knex.select('column1').from('table1').where('column1', '2')
        .then(handleData)
        .catch(handleError)
    ])
      .then(([res1, res1]) => ({ res1, res2 }));
    
        2
  •  1
  •   Mark    7 年前

    knex.select().then() 返回一个承诺,因此您不需要用另一个承诺包装它,您只需要设置链 then() 然后把整个东西还给我。结果就是 getData 从上一次返回承诺。您可以从中返回所需的值 然后() 这将使呼叫方可以使用它。例如:

    function run() {
        getData()
        .then(handledData => console.log(handledData) /* do something with data */)
    }
    
    function getData() {
        let handledData = {};
        // need to return this promise to callers can access it
        return knex.select('column1').from('table1').where('column1', '1')
        .then(data => handledData.res1 = handleData(data))
        .then(() => knex.select('column1').from('table1').where('column1', '2'))
        .then(data => {
            handledData.res2 = handleData(data)
            return handledData
        })
        .catch(handleError);
    }
    

    你也可以设置这个来通过 handledData 对象考虑了链,但在这种情况下不需要这样做。

    函数 handleData() 是同步的,所以您不需要使它成为异步函数。

    推荐文章