为什么.then()在promise实际解决之前被解雇了?

时间:2016-04-15 20:25:40

标签: javascript es6-promise

我正在尝试从异步任务中返回promise,以便我可以使用 .then()调用使它们同步。不幸的是,我正在经历一些真正奇怪的行为。基本上,第三个 then()在第二个解决之前执行。有人可以解释发生了什么吗?这是我的代码:

function runReleaseLoop() {
  console.log('Starting release loop');
  const themes = ['blue', 'red'];
  return new Promise(resolve => {
    buildReleases(themes, resolve);
  })
}

function buildReleases(themes, onComplete) {
  console.log(themes);
  if (themes.length === 0) {
    onComplete();
  } else {
    const theme = themes.pop();
    Promise.resolve()
      .then(setTheme(theme))
      .then(someDelayedTask(theme))
      .then(buildReleases(themes, onComplete));
  }
}

function setTheme(theme) {
  return new Promise(resolve => {
    console.log(`Setting theme to ${theme}`);
    resolve();
  });
}

function someDelayedTask(theme) {
  console.log(`Starting delayed task related to ${theme}`);
  return new Promise(resolve => {
    setTimeout(() => {
      console.log(`Finished delayed task related to ${theme}`);
      resolve();
    }, 3000)
  });
}

// Run the process
runReleaseLoop()
  .then(() => {
    console.log('Release loop finished')
  });

这是我的控制台输出:

"Starting release loop"
["blue", "red"]
"Setting theme to red"
"Starting delayed task related to red"
["blue"]
"Setting theme to blue"
"Starting delayed task related to blue"
[]
"Release loop finished"
"Finished delayed task related to red"
"Finished delayed task related to blue"

2 个答案:

答案 0 :(得分:1)

您同步调用这些功能(setThemesomeDelayedTaskbuildReleases),然后将其返回值(承诺)传递到then将函数本身传递给当时:

Promise.resolve()
  .then(setTheme(theme))
  .then(someDelayedTask(theme))
  .then(buildReleases(themes, onComplete));

这是一个解决方案:

Promise.resolve()
  .then(_ => setTheme(theme))
  .then(_ => someDelayedTask(theme))
  .then(_ => buildReleases(themes, onComplete));

以下是具有上述更改的代码输出:

Starting release loop
[ 'blue', 'red' ]
Setting theme to red
Starting delayed task related to red
Finished delayed task related to red
[ 'blue' ]
Setting theme to blue
Starting delayed task related to blue
Finished delayed task related to blue
[]
Release loop finished

答案 1 :(得分:0)

第一个问题是,你将promises与回调混合在一起。第二种是你一次调用所有函数setTheme, someDelayedTask, buildReleases

function runReleaseLoop() {
  console.log('Starting release loop');
  const themes = ['blue', 'red'];
  return buildReleases(themes);
}

function buildReleases(themes) {
  console.log(themes);
  if (themes.length === 0) {
    return Promise.resolve();
  }

  const theme = themes.pop();
  return setTheme(theme)
    .then(() => someDelayedTask(theme))
    .then(() => buildReleases(themes));
}

function setTheme(theme) {
  console.log(`Setting theme to ${theme}`);
}

function someDelayedTask(theme) {
  console.log(`Starting delayed task related to ${theme}`);
  return new Promise(resolve => {
    setTimeout(() => {
      console.log(`Finished delayed task related to ${theme}`);
      resolve();
    }, 3000)
  });
}

// Run the process
runReleaseLoop()
  .then(() => console.log('Release loop finished'));