Node.js:承诺在resolve()调用之前已解决?

Pup*_*per 2 javascript node.js promise

我对Node.js及其异步行为非常陌生。

我正在尝试获取一个文件,保存它的副本,在复制的文件后追加一行,然后按顺序开始使用复制的文件。

这大致就是我现在所拥有的...

var first = new Promise(function(resolve, reject) {
    console.log("1");
    var readStream = fs.createReadStream("file.txt");
    var writeStream = fs.createWriteStream("file-copy.txt");
    readStream.on("end", function () {
        writeStream.end();
    });

    var pipeAction = readStream.pipe(writeStream);
    pipeAction.on("close", function() {
        console.log("2");
        resolve();
    });
});

var second = new Promise(function(resolve, reject) {
    console.log("3");
    fs.appendFile("file-copy.txt", "\nA NEW LINE TO INSERT",  function (err) {

    });
    console.log("4");
    resolve();
});

var third = new Promise(function(resolve, reject) {
    // do something with the modified, copied file
    console.log("5");
});

first.then(second).then(third);
Run Code Online (Sandbox Code Playgroud)

输出显示为1 3 4 5 2而不是1 2 3 45。谁能分享一些有关为什么“ first”在打印“ 2”之前就能够解析的信息?

谢谢!

Set*_*eth 5

您使用的诺言不正确。在您的示例中,您立即调用了您的承诺。由于他们的执行程序函数(带有resolve/ rejectparams 的回调)在实例化承诺的瞬间被调用,因此您将立即记录1,3,4和5。由于console.log('2')包装在异步操作的回调中,因此它被推迟了,最终被最后叫。

实现您要尝试的操作的正确方法是将变量设置为函数本身,return而不是您的promise。这样,当您的firstsecondthird函数被调用时,它们立即调用其执行程序并开始控制流程。但是,您必须return兑现承诺,否则您将打破承诺链。

function first() {
  return new Promise(function(resolve, reject) {
    console.log("1");
    var readStream = fs.createReadStream("file.txt");
    var writeStream = fs.createWriteStream("file-copy.txt");
    readStream.on("end", function() {
      writeStream.end();
    });

    var pipeAction = readStream.pipe(writeStream);
    pipeAction.on("close", function() {
      console.log("2");
      resolve();
    });
  });
}

function second() {
  return new Promise(function(resolve, reject) {
    console.log("3");
    fs.appendFile("file-copy.txt", "\nA NEW LINE TO INSERT", function(err) {

    });
    console.log("4");
    resolve();
  });
}

function third() {
  return new Promise(function(resolve, reject) {
    // do something with the modified, copied file
    console.log("5");
  });
}

first().then(second).then(third);
Run Code Online (Sandbox Code Playgroud)

产量:

1
2
3
4
5
Run Code Online (Sandbox Code Playgroud)

这是一个可以使用的工作版本:

function first() {
  return new Promise(function(resolve, reject) {
    console.log("1");
    var readStream = fs.createReadStream("file.txt");
    var writeStream = fs.createWriteStream("file-copy.txt");
    readStream.on("end", function() {
      writeStream.end();
    });

    var pipeAction = readStream.pipe(writeStream);
    pipeAction.on("close", function() {
      console.log("2");
      resolve();
    });
  });
}

function second() {
  return new Promise(function(resolve, reject) {
    console.log("3");
    fs.appendFile("file-copy.txt", "\nA NEW LINE TO INSERT", function(err) {

    });
    console.log("4");
    resolve();
  });
}

function third() {
  return new Promise(function(resolve, reject) {
    // do something with the modified, copied file
    console.log("5");
  });
}

first().then(second).then(third);
Run Code Online (Sandbox Code Playgroud)

  • 非常不客气。异步编程可能难以捉摸。 (2认同)