承诺链接功能

时间:2017-04-23 11:05:28

标签: javascript es6-promise

我正在尝试将promises用于一个小型新项目。但是我在理解如何使用函数更好地组织代码方面遇到了一些问题。问题是,我希望我的函数处理事情,我希望我的主要代码处理其他事情。所以,让我们看看这段代码:

in my function something

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

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

第一个是创建变量,对变量使用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/1/):

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

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

{{1}}

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

2 个答案:

答案 0 :(得分:2)

你可以简单地返回值(或重新抛出错误),它将在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()方法时捕获它。

答案 1 :(得分:1)

你可以写一个tap函数,进入一个promise链,并在传递结果时执行一些操作,以及一个并行的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条款来减少破坏承诺链的风险,这些条款只是意味着用于记录或其他副作用。

您还可以使用Promise(我们称之为tap)来污染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));
}