使用蓝鸟时,操作不正常

Actions are out of order, when using bluebird

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

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

  1. 重命名所有 mp4 文件,因此所有文件都不包含 space。

  2. 将所有 mp4 转换为 mp3

  3. kill adb server (with child process exec)

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

  5. 推送到我的androidphone

一些示例代码:

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.

如您所见,上面的输出是 out of orders

  1. 它会杀死 adb 服务器(使用 cild process exec)
  2. 重命名所有 mp4 文件,因此所有文件都不包含 space。
  3. 将所有音乐推送到我的 android phone
  4. 启动 adb 服务器(带子进程 exec)
  5. 将所有 mp4 转换为 mp3

您的代码暗示您已经开始了musicPromiseadbKillPromiseadbStartPromiseadbPushPromise所代表的操作,而您是运行他们都在同一时间飞行。因此,它们将按照它们自然完成的任何顺序完成,您无法直接控制它。

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

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

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

其中 a()b()c() 是 return 一个 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();
      });
    });
  }

请注意,它现在是一个 return 承诺的函数,因此可以根据需要调用它(仅在需要调用它时)并且我还向它添加了错误处理,因此它拒绝如果有一个错误。

并且,对您定义的所有其他变量执行此操作,这些变量对应于您要排序的异步操作之一。那么,你可以这样做:

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);
});