应该由 Promise 调用同步代码。然后创建一个新的 Promise

Should synchronous code called by Promise .then create a new Promise

我实现了一些代码,其中异步代码后跟一些同步函数。例如:

function processSomeAsyncData() {
  asyncFuncCall()
    .then(syncFunction)
    .catch(error);
}

如果我没理解错的话then也是一个Promise。那么,我是否也应该在同步代码中创建一个承诺?

function syncFunction() {
  const p = new Promise (function (resolve, reject) {
    //Do some sync stuff
    ...
    resolve(data);
  }
  return p;
}

如果没有必要,如果发生错误,您如何拒绝来自同步代码的承诺?

可选。

如果您 return 来自 syncFunction 的承诺,那么只有在新承诺解决后您的原始承诺才会解决,并且新承诺所 return 的任何值都将被传递链中的下一个 then

如果您 return 一个非 Promise 值,它将被传递到链中的下一个 then

要从 syncFunction 中拒绝,只需抛出异常即可。

您无需显式创建新承诺。有一个更简单的方法。

这个例子是人为设计的,因为它永远不会失败,但重点是您不必创建一个承诺,也不必 return 一个 resolve(val)。

function syncFunction() {
  var j = "hi"
  if(j){
    return j;
  }
  return new Error('i am an error');
}

这会起作用:

asyncFunction()
  .then(syncFunction);

但如果你反过来做:

syncFunction()
  .then(asyncFunction);

您必须将 syncFunction 定义为:

function syncFunction() {

  var j = "hi"
  return new Promise((resolve, reject) => {
    if(j){
      return resolve(j);
    }
    return reject('error');
  })  
}

编辑: 为了向所有非信徒证明,请在您的计算机上本地试一试这家伙。证明您有这么多选择。 :)

var Promise = require('bluebird');


function b(h) {
    if(h){
        return h;
    }
    return Promise.resolve('hello from b');
}

function a(z) {
    return new Promise((resolve, reject)=> {
        if(z){return resolve(z)};
        return resolve('hello from a');
    })
}

a().then(b).then(x => console.log(x)).catch(e => console.log(e));
b().then(a).then(x => console.log(x)).catch(e => console.log(e));

没有。同步函数可以从同步代码中调用,并且应该总是同步失败!它们不需要以任何方式符合异步调用者。如果发生错误,只需抛出一个错误。试一试:

var asyncFuncCall = () => Promise.resolve();

function syncFunction() {
  throw new Error("Fail");
}

asyncFuncCall()
  .then(syncFunction)
  .catch(e => console.log("Caught: " + e.message));

这是有效的,因为传递给 .then 的函数抛出的异常被转换为拒绝它应该 return.

的承诺

此外,由函数传递给 .then 的任何值 return 都会转换为使用该值解决的承诺。调用函数的承诺代码会处理这个问题。

这让您可以毫无问题地混合同步和异步代码:

asyncFuncCallOne()
  .then(() => {
    var x = syncFunction();
    return asyncFuncCallTwo(x);
  })
  .catch(e => console.log(e.message));