承诺通过功能链接



我正在尝试将承诺用于一个小项目。但是,我在理解如何通过功能更好地组织代码时遇到了一些问题。问题是,我希望我的功能能够处理问题,而我的主要代码来处理其他事情。因此,让我们看看此代码:

function doSomething (isGoingToResolve = true) {
    return new Promise((resolve, reject) => {
    if (isGoingToResolve) {
        resolve("something")
    } else {
        reject("something else")
    }
  }).then(response => {
    console.log("in my function",response)
  }).catch(error => {
    console.log("in my function",error)
  })
}
doSomething().then(response => {
    console.log("in my main call", response)
})

使用此代码,控制台将记录in my function somethingin my main call undefined:https://jsfiddle.net/hkacvw2g/

所以我找到了解决问题的两种解决方案,但我只是不喜欢它们:

第一个是创建一个变量,在变量上使用.then(),然后返回变量(https://jsfiddle.net/hkacvw2g/1/(:

function doSomething (isGoingToResolve = true) {
    let promise = new Promise((resolve, reject) => {
    if (isGoingToResolve) {
        resolve("something")
    } else {
        reject("something else")
    }
  })
  promise.then(response => {
    console.log("in my function",response)
  }).catch(error => {
    console.log("in my function",error)
  })
  return promise
}

和第二个解决方案(https://jsfiddle.net/hkacvw2g/2/(:

function doSomething (isGoingToResolve = true) {
    return new Promise((resolve, reject) => {
    if (isGoingToResolve) {
        resolve("something")
    } else {
        reject("something else")
    }
  }).then(response => {
    console.log("in my function",response)
    return new Promise(resolve => {
        resolve(response)
    })
  }).catch(error => {
    console.log("in my function",error)
    return new Promise((resolve,reject) => {
        reject(error)
    })
  })
}

我是否错过了解决问题的更好解决方案?

您可以简单地返回值(或重新输入错误(,然后将其在Promise链中解决:

function doSomething (isGoingToResolve = true) {
  return new Promise((resolve, reject) => {
    if (isGoingToResolve) {
      resolve("something")
    } else {
      reject("something else")
    }
  }).then(response => {
    console.log("in my function",response)
    return response;
  }).catch(error => {
    console.log("in my function",error)
    throw error;
  })
}

您可能不希望throw error,这取决于您要如何处理拒绝。这样,当您重新输入错误时,请在调用doSomething()方法时捕获它。

您可以编写一个tap函数,点击前景链,并在传递结果时做某事,以及并行tapCatch函数,以在重新磨损它们时插入错误:

const tap      = fn => value  => { fn(value);  return value; };
const tapCatch = fn => reason => { fn(reason); throw reason; };

现在您可以将代码写为:

function doSomething(isGoingToResolve = true) {
  (isGoingToResolve ? 
    Promise.resolve("something") : 
    Promise.reject("something else")
  )
  .then( tap     (response => console.log("in my function", response)))
  .catch(tapCatch(error    => console.log("in my function", error)));
}
doSomething()
  .then(response => console.log("in my main call", response));

但是,实际上您的第一个解决方案更好。它通过无意间忘记或不意识到您必须返回then条款中的原始价值或在catch条款中返回原始价值而降低了弄乱承诺链的风险。

您还可以用tap之类的东西污染Promise原型(我们将其称为thenDo(,使其更容易使用:

Promise.prototype.thenDo = function(ifFulfilled, ifRejected) {
  return this.then(
    value => { ifFulfilled(value); return value; },
    reason => { ifRejected(reason); throw reason; });
};
Promise.prototype.catchDo = function(ifRejected) {
  return this.catch(reason => { ifRejected(reason); throw reason; });
};

现在您可以写

function doSomething(isGoingToResolve = true) {
  (isGoingToResolve ? 
    Promise.resolve("something") : 
    Promise.reject("something else")
  )
  .thenDo (response => console.log("in my function", response))
  .catchDo(error    => console.log("in my function", error));
}

最新更新