如何使用js Promise消除厄运的金字塔

时间:2016-09-10 15:34:39

标签: javascript es6-promise

我试图理解如何使用js Promise api来折射具有大量嵌套IF的代码。

例如,从localstorage获取JSON对象时,普通代码看起来像

function $storage(key,default) {
  let json = localStorage.getItem(key);

  if(json === null) return default;

  try{  // <-- need try catch in case value was not valid json object
    json = JSON.parse(json); 
  } catch (e) {
    json = default;
  }
  return typeof json === 'object' ? json : default;
}

此代码的可读性不是那么好。所以我想可能是我可以利用js Promise将其重写为

function $storage (key, default) {
 let ret;

 let promise = new Promise( (y,n) => y(localStorage) )
 .then( ls => JSON.parse(ls.getItem(key)) )
 .then( json => typeof json === 'object' ? json : HOW_TO_THROW_ERROR() )
 //on more validation step if needed
 .then( json => typeof json === 'object' ? json : HOW_TO_THROW_ERROR() )
 .then( valid_json => { return = valid_json } )
 .catch( error => { ret = default; console.warn('json invalid',e); } );

 return ret;

}

现在我想知道如何在内部抛出一个异常,以便catch可以捕获它并执行默认值?

这是js承诺的有效用法,我在浪费性能

5 个答案:

答案 0 :(得分:1)

您可以使用Promise.reject()引发错误:

function $storage (key, default) {
 let ret;

 let promise = new Promise( (y,n) => y(localStorage) )
 .then( ls => JSON.parse(ls.getItem(key)) )
 .then( json => typeof json === 'object' ? json : Promise.reject("invalid json") )
 .then( valid_json => { return = valid_json } )
 .catch( err => { ret = default; console.warn(err.message); } );

 return ret;

}

虽然我发现以下更易读和惯用。

function $storage(key,default) {
  let json = localStorage.getItem(key);
  if(json === null ||  typeof json !== 'object') json = default;

  try{  
    json = JSON.parse(json); 
  } catch (e) {
    json = default;
  } finally {
  return json
  }
}

正如您所知,Promise用于异步计算。任何其他用途可能会混淆其他程序员。

答案 1 :(得分:1)

您可以使用thrown抛出错误,然后在catch方法中处理它们

var p1 = new Promise(function(resolve, reject) {
  resolve('Success');
});

p1.then(function(value) {
  console.log(value); // "Success!"
  throw 'oh, no!';
}).catch(function(e) {
  console.log(e); // "oh, no!"
}).then(function(){
  console.log('after a catch the chain is restored');
}, function () {
  console.log('Not fired due to the catch');
});

// The following behaves the same as above
p1.then(function(value) {
  console.log(value); // "Success!"
  return Promise.reject('oh, no!');
}).catch(function(e) {
  console.log(e); // "oh, no!"
}).then(function(){
  console.log('after a catch the chain is restored');
}, function () {
  console.log('Not fired due to the catch');
});

但是如果在异步函数中抛出一些错误,则永远不会调用catch。

// Errors thrown inside asynchronous functions will act like uncaught errors
var p2 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    throw 'Uncaught Exception!';
  }, 1000);
});

p2.catch(function(e) {
  console.log(e); // This is never called
});

来源:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch

答案 2 :(得分:0)

在JavaScript中,您可以使用关键字throw来引发任何错误。 MDN的例子:

throw "Error2"; // generates an exception with a string value
throw 42;       // generates an exception with the value 42
throw true;     // generates an exception with the value true
throw new Error("Error");

答案 3 :(得分:0)

function $storage (key, default) {
 let ret;

 let promise = new Promise( (y,n) => y(localStorage) )
 .then( ls => JSON.parse(ls.getItem(key)) )
 .then( json => typeof json === 'object' ? json : throw new Error("invalid json") )
 //on more validation step if needed
 .then( json => typeof json === 'object' ? json : throw new Error("invalid json") )
 .then( valid_json => { return = valid_json } )
 .catch( err => { ret = default; console.warn(err.message); } );

 return ret;

}

你基本上可以执行以下操作,因为如果解析失败,它将被自动捕获。

function $storage (key, default) {
 let ret;

 let promise = new Promise( (y,n) => y(localStorage) )
 .then(ls => JSON.parse(ls.getItem(key)) )
 .then(valid_json => { return = valid_json } )
 .catch(err => { ret = default; console.warn(err.message); } );

 return ret;

}

答案 4 :(得分:0)

我看到的问题只是JSON.parse,将它包装在一个更有用的函数中,你得到类似的东西:

function safeParse(x) {
    try {
        return JSON.parse(x);
    } catch(e) {
        // Log the problem
        return null;
    }
}

function parmval(key, defval) {
    var json = safeParse(localStorage.get(key));
    return (typeof json === "object") ? json : defval;
}

Promise是关于异步操作,而不是IF。