【问题标题】:Actions are out of order, when using bluebird使用蓝鸟时,动作出现故障
【发布时间】:2017-03-20 11:19:17
【问题描述】:

完整代码:https://github.com/kenpeter/clip_to_music

基本上,这个简单的nodejs脚本应该按顺序执行这些动作

  1. 重命名所有 mp4 文件,因此没有包含空格的文件。

  2. 将所有 mp4 转换为 mp3

  3. 杀死 adb 服务器(带子进程 exec)

  4. 启动 adb 服务器(带子进程 exec)

  5. 推送到我的安卓手机

一些示例代码:

renamePromise
  .then(() => {
    return musicPromise;
  })
  .then(() => {
    return adbKillPromise;
  })
  .then(() => {
    return adbStartPromise;
  })
  .then(() => {
    return adbPushPromise;
  })
  .then(() => {
    console.log('---- all done----');
    process.exit(0);
  });

输出是这样的,乱序

; yarn start
yarn start v0.21.3
$ node clip_to_music.js 

---adb kill---
-- Rename one file --
/home/kenpeter/Videos/4K Video Downloader/1.mp4
-- Rename one file --
/home/kenpeter/Videos/4K Video Downloader/2.mp4
--- rename all files done ---
adb push /var/www/html/test/testme/clip_to_music/audio/1.mp3 /sdcard/Music
adb push /var/www/html/test/testme/clip_to_music/audio/2.mp3 /sdcard/Music
---- done push all music ---
* daemon not running. starting it now on port 5037 *
* daemon started successfully *

---adb start---
single mp3 done!

single mp3 done!

--------- all mp3 conversion done --------
---- all done----
Done in 10.79s.

如您所见,上面的输出无序

  1. 它会杀死 adb 服务器(使用 cild 进程执行)
  2. 重命名所有 mp4 文件,因此没有包含空格的文件。
  3. 将所有音乐推送到我的安卓手机
  4. 启动 adb 服务器(带有子进程 exec)
  5. 将所有 mp4 转换为 mp3

【问题讨论】:

  • 问题/疑问是什么?

标签: android node.js promise bluebird


【解决方案1】:

您的代码意味着您已经启动了由musicPromiseadbKillPromiseadbStartPromiseadbPushPromise 表示的操作,并且您正在同时运行它们。因此,它们将按照自然完成的任何顺序完成,而您无法直接控制。

请记住,promise 只是用于监控异步操作的工具。由于您已经有了 Promise,因此您必须已经开始异步操作,因此您的 Promise 链根本无法控制活动的顺序。它确实控制您处理结果的顺序,但根本不控制活动本身的顺序。

要真正对操作本身进行排序,您不需要开始后续操作,直到您想要在它之前完成的操作更像这样:

a().then(b).then(c).catch(err => { /* handler error here */});

其中a()b()c() 是返回promise 的函数,每个函数都启动相应的异步操作。

作为你的一个操作的例子,改变这个:

// adb kill
var adbKillPromise = new Promise((resolve, reject) => {
  exec("adb kill-server", (err, stdout, stderr) => {
    if (err) {
      console.error(err);
      return;
    }

    console.log(stdout);
    console.log('---adb kill---');
    resolve();
  });
});

成为一个以后可以调用的函数:

  // adb kill
  function adbKill() {
    return new Promise((resolve, reject) => {
      exec("adb kill-server", (err, stdout, stderr) => {
        if (err) {
          console.error(err);
          reject(err);
          return;
        }

        console.log(stdout);
        console.log('---adb kill---');
        resolve();
      });
    });
  }

请注意,它现在是一个返回承诺的函数,因此可以按需调用(仅在需要调用它时),我还向它添加了错误处理,以便在出现错误时拒绝。

并且,对您定义的与您想要排序的异步操作之一相对应的所有其他变量执行此操作。然后,您可以这样做:

rename().then(music).then(adbKill).then(adbStart).then(adbPush).then(() => {
    console.log('---- all done----');
    process.exit(0);
}).catch(err => {
    console.log('Error', err);
    process.exit(1);
});

【讨论】:

  • Github 代码已更新。 var musicPromise = () => { new Promise((resolve, reject) => {......}) },我做了这样的事情,看起来行动是有序的。但是在 musicPromise 中,只有 1 个文件被转换并且它从不打印“single mp3 done!”我应该为此特定代码创建一个新问题吗?
  • @kenpeter - 这是一个教科书示例,说明为什么应该将与您的问题相关的代码粘贴到实际问题中。现在出现并阅读您的问题并点击您的代码链接的任何人都会看到已经修复的代码而不是原始代码,并且不会理解您的问题,因为您已经编辑了该代码参考以显示我建议的修复。所以,你有点毁了你的问题作为未来参考的价值,这是堆栈溢出的目标。
  • @kenpeter - 我认为您的原始问题已经在这里得到了回答。 musicPromise 内部的一个新问题应该是一个新问题。并且,请将相关代码粘贴到您提出的所有问题中,以避免上述问题。
  • 是的,你是对的。 stackoverflow.com/questions/42895472/…
猜你喜欢
  • 1970-01-01
  • 2019-10-06
  • 1970-01-01
  • 1970-01-01
  • 2020-01-21
  • 1970-01-01
  • 2014-12-22
  • 2019-07-05
  • 1970-01-01
相关资源
最近更新 更多