Promise.then()但函数异步运行

Promise.then() but functions run async

本文关键字:函数 异步 运行 then Promise      更新时间:2023-09-26

我是Javascript新手,正在做爬虫,我已经创建了4个承诺作为这些

var openConfig = new Promise((resolve, reject) => {
  fs.readFile('./config.json', (err, data) => {
    if (err) throw err;
    config = JSON.parse(data);
    client = new MsTranslator({
      client_id: config.translatorId,
      client_secret: config.translatorSecret
    }, true)
    resolve();
  })
})
var openFile = new Promise((resolve, reject) => {
  console.log('Opening file...')
  fs.readFile('./writing/writing.json', (err, data) => {
    if (err) throw err;
    writing = JSON.parse(data);
    console.log('Done parsing file');
    resolve();
  })
})
var ask = new Promise((resolve, reject) => {
  var rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  })
  rl.question('Which lesson do you want to add? ', (ans) => {
    lessonId = ans;
    rl.close();
    resolve();
  })
})
var createLesson = new Promise((resolve, reject) => {
  console.log('Now processing lesson ' + lessonId);
})

则调用第一个Promise

openConfig
  .then(() => {
    return openFile;
  })
  .then(() => {
    return ask;
  })
  .then(() => {
    return createLesson;
  })

但是当我运行时,控制台显示

Opening file...
Which lesson do you want to add? Now processing lesson undefined
Done parsing file

,我理解为我的承诺是错误的,我的函数运行异步。你能帮我修一下吗?

谢谢。

承诺没有"调用"。在then链中,您只能按顺序等待它们——但是当您创建承诺时,任务已经开始了。如果你想对动作进行排序,把它们放在函数中。

顺便说一句,你的代码包含多个典型错误。不要使用全局变量,并且总是在尽可能低的级别承诺:
function openFile(path) {
  return new Promise((resolve, reject) => {
    fs.readFile('./config.json', (err, data) => {
      if (err) reject(err); // never `throw err` in non-promise callbacks!
      else resolve(data);
    });
  });
}
function openJSON(path) {
  return openFile(path).then(JSON.parse);
}
function openConfig(path) {
  return openJSON(path).then(config =>
    new MsTranslator({
      client_id: config.translatorId,
      client_secret: config.translatorSecret
    }, true)
  )
}
function ask(question) {
  return new Promise((resolve, reject) => {
    var rl = readline.createInterface({
      input: process.stdin,
      output: process.stdout
    })
    rl.question(question, ans => {
      rl.close();
      resolve(ans); // always resolve to *something*
    });
  });
}
readConfig('./config.json')
.then(client => {
  console.log('Opening file...')
  return openJSON('./writing/writing.json');
})
.then(writing => {
  console.log('Done parsing file');
  return ask('Which lesson do you want to add? ');
})
.then(lessonId => {
  console.log('Now processing lesson ' + lessonId);
});

不要将新的Promise赋值给vars(它们在创建后立即运行),而应该将它们包装成函数,然后返回一个新的Promise

为了帮助你理解,这里有一个简化的例子:

function p1 (data) {
    return new Promise(function (resolve, reject) {
        resolve(Object.assign(data, {a:1}));
    });
}
function p2 (data) {
    return new Promise(function (resolve, reject) {
        resolve(Object.assign(data, {b:2}));
    });
}
function p3 (data) {
    return new Promise(function (resolve, reject) {
        resolve(Object.assign(data, {c:3}));
    });
}
p1({z:0})
.then(p2)
.then(p3)
.then((data)=>console.log(data))

结果是{ z: 0, a: 1, b: 2, c: 3 }

如果您想尝试一下上面的内容,请参阅此处:https://repl.it/DwNB/0


另一个注意事项,如果您使用承诺,您还应该在最后的.catch()中处理链中的错误,而不是在中途同步throw。这就是reject回调的作用!