2014-09-17 2 views
5

Я пишу код, который в настоящее время выглядит так, потому что у меня есть зависимости в моем коде. Мне было интересно, есть ли более чистый способ сделать это с помощью Promise.all()? Вот мой псевдо-код:Метод Promise.all() Bluebird, когда одно обещание зависит от другого

 return someService.getUsername() 
      .then(function(username) { 
       user = username; 
      }) 
      .then(function() { 
       return someService.getUserProps(user); 
      }) 
      .then(function(userProps) { 
       userProperties = userProps; 
       return someService.getUserFriends(user); 
      }) 
      .then(function(userFriends) { 
       friends = userFriends; 
      }) 
      .catch(error) 
      .finally(function(){ 
       // do stuff with results 
      }); 

Важно то, что мне нужно пользователю, прежде чем я могу сделать второй два вызова для getUserProps() и getUserFriends(). Я думал, что я мог бы использовать Promise.all() для этого, как так:

var user = someService.getUsername() 
    .then(function(username) { 
     user = username; 
    }) 
var getUserProps = someService.getUserProps(user); 
var getUserProps = someService.getUserFriends(user); 

return Promise.all(user, getUserProps, getUserFriends, function(user, props, friends) { 
    // do stuff with results 
}) 

Но я не могу получить эту работу. Это правильный случай для использования .all?

ответ

8

Promise.all() предназначен для параллельной работы, когда вы запускаете кучу асинхронных операций для запуска в одно и то же время, а затем оно сообщает вам, когда все будет сделано.

Это не последовательность в сравнении с пополнением другого в любом случае. Таким образом, вы не можете использовать его, чтобы дождаться, когда пользователь будет готов, а затем другие операции будут использовать этот пользователь. Он просто не предназначен для этого.

Сначала вы можете получить пользователя, а затем, когда это будет завершено, вы можете использовать Promise.all() с двумя другими операциями, которые, как я думаю, могут выполняться одновременно и не зависят друг от друга.

var user; 
someService.getUsername().then(function(username) { 
    user = username; 
    return Promise.all(getUserProps(user), getUserFriends(user)); 
}).then(function() { 
    // do stuff with results array 
}).catch(function() { 
    // handle errors 
}); 
4

Вы можете использовать .all, но вы будете иметь, чтобы убедиться, что они выполняются последовательно код, вы можете сделать это, .then их ING, как вы сделали. Если вы это сделаете, вы должны использовать .join, который является сокращением для .all([...]).spread(....

var user = someService.getUsername(); 
var props = user.then(getUserProps) 
var friends = user.then(getUserFriends) 
Promise.join(user, props, friends, function(user, props, friends) { 

    // everything is available here, everything is synchronized 
}); 

Если то, что вы пытаетесь решить это замыкание/раскрой вопрос - то это способ сделать это.

+0

Это не работает для меня, потому что мне нужно передать переменную getUserProps(), и у меня ее нет, когда я устанавливаю переменную реквизита во второй строке. – Jeff

+1

@Jeff Пользовательская переменная автоматически передается функции getUserProps, так как это значение разрешения обещания - точно так же, как в вашем примере. Вы можете использовать '.bind', если вам нужно передать дополнительные параметры или анонимную функцию. –

+0

ohhh .... так что определение реквизита могло бы быть: var props = user.then (getUserProps (пользователь)); ? – Jeff

1

Promise.all() - это способ выполнения списка обещаний параллельно, но если мы хотим выполнить список обещаний в серии, где каждый зависит от другого, мы должны решить его несколько иначе

// Promise returning functions to execute 
function doFirstThing(){ return Promise.resolve(1); } 
function doSecondThing(res){ return Promise.resolve(res + 1); } 
function doThirdThing(res){ return Promise.resolve(res + 2); } 
function lastThing(res){ console.log("result:", res); } 

var fnlist = [ doFirstThing, doSecondThing, doThirdThing, lastThing]; 

// Execute a list of Promise return functions in series 
function pseries(list) { 
    var p = Promise.resolve(); 
    return list.reduce(function(pacc, fn) { 
    return pacc = pacc.then(fn); 
    }, p); 
} 

pseries(fnlist); 
// result: 4 
Смежные вопросы