简体   繁体   English

Javascript承诺链执行不正常

[英]Javascript promise chain executing out of order

I made a "promisified" version of fs.readFile using Javascript's native Promise, which parses a JSON file and returns the object when resolving. 我做了一个“promisified”版本fs.readFile使用JavaScript的本地承诺,解决时,它解析JSON文件,并返回对象。

function readFileAsync(file, options) {
  return new Promise(function (resolve, reject) {
    fs.readFile(file, options, function(err, data) {
      if (err) {
        reject(err);
      } else {
        var object = JSON.parse(data);
        resolve(object);
      }
    });
  });
}

I first tried chaining the promises myself, but for some reason first the districts.variable1 from promise 1 gets logged, then comparePersonalities is called in promise 3, which gives an error because user is still undefined, and then user.variable2 gets logged from promise 2. 我首先尝试自己链接诺言,但由于某种原因,首先会记录诺言1中的districts.variable1 ,然后在诺言3中调用comparePersonalities ,这会产生错误,因为用户仍未定义,然后从诺言中记录user.variable2 2。

var user, district;
readFileAsync(file1, 'utf8').then(function (data) {
  districts = data;
  console.log(districts.variable1);
}).then(readFileAsync(file2, 'utf8').then(function (data) {
  user = data;
  console.log(user.variable2);
})).then(function (result) {
  comparePersonalities(districts, user);
}).catch(function (e) {
  console.log(e);
});

I also tried an alternate approach using Promise.all but this still results in an incorrect ordering and the comparePersonalities failing. 我还尝试了使用Promise.all的另一种方法,但这仍然会导致顺序错误和comparePersonalities失败。

Promise.all([readFileAsync(file1), readFileAsync(file2)]).then(function (first, second) {
  districts = first;
  user = second;
  comparePersonalities(districts, user);
});

When logging the resolved objects within the promise everything seems to work well, I can't figure out why everything is eventually initialized but the last promise runs before the second promise has finished. 当在promise中记录已解决的对象时,一切似乎都运行良好,我无法弄清楚为什么最终都会初始化所有东西,但是最后一个promise在第二个promise完成之前运行。 What am I doing wrong in both the chained promise and in Promise.all ? 在链式承诺和Promise.all我在做什么错?

Promise.all is much more appropriate for your use case. Promise.all更适合您的用例。 You made a mistake in the callback: the outer promise is resolved with an array of results (in the same order as the inner promises), so then(function (first, second) {...}) is incorrect. 您在回调中犯了一个错误:外部诺言通过结果数组 (与内部诺言的顺序相同)解析,因此then(function (first, second) {...})不正确。 Try something like this 试试这个

Promise.all([
  readFileAsync(file1, 'utf8'),
  readFileAsync(file2, 'utf8')
]).then(function (results) {
  // note that "results" is an array of two values
  var districts = results[0];
  var user = results[1];
  comparePersonalities(districts, user);
});

You have to return the Promises each time for chaining: 您每次必须返回Promises进行链接:

readFileAsync(file1, 'utf8').then(function(data) {
    districts = data;
    console.log(districts.variable1);
    return readFileAsync(file2, 'utf8');
}).then(function(data) {
    user = data;
    console.log(user.variable2);
    comparePersonalities(districts, user);
}).catch(function(e) {
    console.log(e);
});

comparePersonalities(districts, user) will only work if your variable districts is declared at a higher scope. comparePersonalities(districts, user)仅在您的可变districts在更高范围内声明时才起作用。 Otherwise it will be undefined once you reach this function. 否则,一旦达到此功能,它将是不确定的。

Promises are always resolved with only one value. 始终只用一个值解决承诺。 That's really important, and actually simplifies a lot of things, since you always know how many elements to expect. 这确实很重要,并且实际上简化了很多事情,因为您始终知道期望多少个元素。

The first example 第一个例子

You've made a mistake, in which you are passing a Promise to the .then method, when in reality it always expects a function. 您犯了一个错误,即将Promise传递给.then方法,而实际上它总是希望有一个函数。 Notice the snippet readFileAsync(file2, 'utf8') is nicely wrapped in an anonymous function. 注意,片段readFileAsync(file2, 'utf8')很好地包装在一个匿名函数中。

var user, district;
readFileAsync(file1, 'utf8').then(function (data) {
  districts = data;
  console.log(districts.variable1);
})
  .then(function () { return readFileAsync(file2, 'utf8') })
  .then(function (data) {
    user = data;
    console.log(user.variable2);
  }).then(function (result) {
    comparePersonalities(districts, user);
  }).catch(function (e) {
    console.log(e);
  });

The second example 第二个例子

But, in that case you're probably better off using the Promise.all method, as the promises get resolved and nicely returned in your next funciton call. 但是,在这种情况下,最好使用Promise.all方法,因为承诺会得到解决,并在下一个函数调用中很好地返回。 The problem in your snippet is that promises always resolve one single object, and in the case of Promise.all , you should be expecting one single array. 您的代码段中的问题是Promise.all总是解析一个对象,对于Promise.all ,您应该期望一个数组。 You can actually use es6 destructuring to simplify your code: 您实际上可以使用es6解构来简化代码:

Promise.all([readFileAsync(file1), readFileAsync(file2)])
  .then(function ([districts, user]) {
    comparePersonalities(districts, user);
  });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM