Javascript承诺链无序执行

时间:2016-12-13 00:54:00

标签: javascript node.js promise chaining

我使用Javascript的本机Promise创建了fs.readFile的“promisified”版本,它解析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);
      }
    });
  });
}

我首先尝试自己链接承诺,但出于某种原因首先记录了来自promise 1的districts.variable1,然后在promise 3中调用comparePersonalities,这会产生错误,因为用户仍未定义,然后从promise 2中记录user.variable2

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

我还尝试了使用Promise.all的替代方法,但这仍导致订单错误且comparePersonalities失败。

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

当在promise中记录已解析的对象时,一切似乎都运行良好,我无法弄清楚为什么一切都最终被初始化,但最后一个promise在第二个promise完成之前运行。在链式承诺和Promise.all中我做错了什么?

3 个答案:

答案 0 :(得分:2)

Promise.all更适合您的用例。你在回调中犯了一个错误:外部的promise用结果的数组来解决(与内部promises的顺序相同),所以then(function (first, second) {...})是不正确的。试试这样的事情

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

答案 1 :(得分:0)

每次链接都必须返回Promise:

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)时,

districts才有效。否则,一旦达到此功能,它将是未定义的。

答案 2 :(得分:0)

始终仅使用一个值解决Promise。这非常重要,实际上简化了很多事情,因为你总是知道要期待多少元素。

第一个例子

你犯了一个错误,你将Promise传递给.then方法,而实际上它总是需要一个函数。请注意,代码段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);
  });

第二个例子

但是,在这种情况下,您可能最好使用Promise.all方法,因为承诺会在您的下一个函数调用中得到解决并很好地返回。 你的代码片段中的问题是promises总是解析一个单独的对象,而在Promise.all的情况下,你应该期待一个单独的数组。您实际上可以使用es6解构来简化代码:

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