根据第一个异步函数

时间:2017-04-02 21:44:49

标签: javascript node.js asynchronous es6-promise

我在数组中有一些数据。

let data = ['firstData', 'secondData'];

第一个对象(firstData)始终存在,secondData可以为null。所以我总是使用它来调用我的异步函数,如:

myAsyncFunction(data[0]).then(result => {
    //do something here
});

如果data[1]存在,我想用myAsyncFunction致电data[1]

我目前的解决方案是嵌套承诺。像这样:

myAsyncFunction(data[0]).then(result => {
    return result;
}).then(result => {
    if(data[1] !== null){
        myAsyncFunction(data[1].then(resultTwo => {
        //dostuff with data
      });
    }
});

我不太喜欢这个解决方案,但确实有效。这一定是更好的方式。 result始终是一个对象。我试过Promise.all,但它不起作用。我认为这是"竞争条件"的一个问题。某种形式(我在这里薄冰)。

我目前的解决方案是唯一的吗?

以下是myAsuncFunction的样子:

myAsyncFunction(personData){
    return new Promise<any> ((resolve, reject) => {

        //Assingen private variables

    secondAsyncFunction(somePersonData).then(result =>
     {

                    //Do some sync stuff

          return someNewData; //not a promise
     })
         .then(thirdAsyncFunction)
         .then(data => {
              resolve(data);
         })
         .catch(error => {
          reject(error);
     });
});

3 个答案:

答案 0 :(得分:1)

Promise.all旨在在数组中具有动态数量的promise时使用,并且您希望将它们组合成一个promise,该promise在数组中的所有promise都已解析时解析。

根据您的使用案例,您应该能够像这样使用它:

data = data.filter(x => x !== null);

Promise.all(data.map(myAsyncFunction)).then((results) => {
    const [resultOne, resultTwo] = results;
    if (resultTwo) {
        // handle resultTwo
    }
    // handle resultOne
});

答案 1 :(得分:0)

鉴于data在承诺结果之前已经静态知道,您不需要将条件置于then回调中 - 您可以使整个链条成为条件:

var promise = myAsyncFunction(data[0]);
if(data[1] !== null){
    promise.then(result =>
        myAsyncFunction(data[1])
    ).then(resultTwo => {
        //dostuff with data
    });
}

一般情况下,请注意嵌套不是坏事,当您想要分支控制流时需要它。只是不要忘记永远return所有(回调)函数的承诺。

答案 2 :(得分:0)

你可以简单地做:

&#13;
&#13;
const stuffOnlyRelatedToSecondData = result2 => /*do something*/

myAsyncFunction(data[0]).then(result => {
    if (data[1] === null) {return null}
    return myAsyncFunction(data[1]).then(stuffOnlyRelatedToSecondData) 
}).then(/*Anything to do after [1] or [1,2]*/)
&#13;
&#13;
&#13;

这样你可以使用相同的链,两种可能的情况如下:

myAsyncFunction(data[0]) --> END
myAsyncFunction(data[0]) --> myAsyncFunction(data[1]) --> END

编辑:

似乎myAsyncFunction可能有承诺泄漏,请尝试使用类似的东西:

const myAsyncFunction = personData => {
    //Assigning private variables
    return secondAsyncFunction(somePersonData).then(result => {
        //Do some sync stuff
        return someNewData; //not a promise
    })
    .then(thirdAsyncFunction)
}

我们可以这样写,因为secondAsyncFunction启动了一个新的Promise,因此我们不需要另一个Promise包装器。并且catch可以放在执行myAsyncFunction

的父Promise链本身中