Promise的十个使用禁令

Promise的十个使用禁令

# resolve(thenable) 与 resolve('non-thenable-object')?

# 不要在 Promise 类方法中定义 async 函数。

# 不要把代码写在 Promise 方法外

# 不要嵌套Promise, 使用 await

# 不要配合回调方法使用 await

# 不要在循环中使用await

# 在Promise链条上添加错误处理

# 不要Reject非Error类型参数

例如:

Promise.reject("非法的参数,请检查")

通常我们外部使用Promise时,会认为catch捕获到的一定是一个继承于Error类的实例化对象。因为 在使用声明式的Promise的构造函数内如果出现未捕获的错误,它就是原生的错误类型,但是JS中并没有要求 我们手动的Reject参数一定要传Error实例,为了简化外部使用,这也属于一个潜规则,很多 Eslint的规则中,都会包含一个Reject只能传继承自Error的实例。

Promise.reject(new Error("Cannot match the proper params"))

如果是因为某一个错误,导致你要使用reject抛出去,并且想要加上一些备注(比如会添加一些在哪个阶段出错的), 这时可以修改 Error 的 message 属性,拼接上自己的备注即可

const processResult = (res) => {
  return new Promise((resolve, reject) => {
    unzip(res, (err, data) => {
      if (err) return reject(err);
      resolve(data);
    })
  })
}
const getProject = () => {
  return fetch(xxxx)
  .then(processResult)
  .catch((sourceError) => {
    // do not use 'return Promise.reject(balabala)'
    sourceError.message = `Failed to get project, detail error ${sourceError.message}`
    return Promise.reject(sourceError)
  })
}

比如上面的例子,getProject依赖于另一个promise,在它返回错误时,不能直接抛出你的备注或描述,需要带上详细的 错误原始类,方便追踪栈信息和错误消息。

# 不要试图调用多次resolve来使then


var p = new Promise( function(resolve,reject){
    click( "#mybtn", resolve );
} );
p.then( function(evt){
    var btnID = evt.currentTarget.id;
    return request( "http://some.url.1/?id=" + btnID );
} )
.then( function(text){
    console.log( text );
} );

# 不要搭配回调函数使用Promise

相比上面的那些,这是一个非常繁琐要求,因为很多库并不能提供Promise状态,需要手动一个个hack他们回掉才能达到理想的使用方式。


在回掉中resolve或者reject一个Promise,固然能完成任务,但久而久之,套的回掉越来越多(基于习惯), promise也就没什么作用了。

const buyRefrigerator = new Promise((resolve) => {
  setTimeout(resolve, 5000)
})

buyRefrigerator.then(openTheDoor)
.then(putTheElephantInIt)
.then(closeTheDoor)
.then(waitingForDead)

单独使用Promise,注册一个个处理函数的方式,相对于层层的回调来说是简便了一些,但是还不够灵活。 就比如说上面,如果用回调处理,至少需要五个语句块包裹着。用Promise处理,可以很清晰的看出他们之间 的处理步骤,而且词法也很扁平化,看着舒服。

Read More