Precautions for using JS Promise

foreword

For js, it is very common for us to use promises at ordinary times, but some places do not use them well. This article introduces common non-standard demonstrations and correct usage of promises.

One, finally use

Usually, during the development process, our pages have loading. Before using Promise, enable loading, and turn off loading at the end. But some friends will end in then and catch, which is not elegant enough. In fact, it is better to end in finally.
Correct example:

  let isLoading = true
  const result = await promiseSuccess()
    .finally(() => {
    
    
      isLoading = false
    })

2. Error capture

You can use .catch and try catch for error capture. The difference between the two is that try catch will interrupt the subsequent code as long as it catches an error, but .catch will not. It needs to combine the resolve result to interrupt the code.

Now we have 2 methods

  • promiseSuccess(),该方法100%返回resolve(true)
  • promiseFail(),该方法100%返回reject(new Error("出错了"))
/** promise成功 */
function promiseSuccess() {
    
    
  return new Promise((resolve) => {
    
    
    resolve(true)
  })
}

/** promise失败 */
function promiseFail(errorStr = '出错了') {
    
    
  return new Promise((resolve, reject) => {
    
    
    reject(new Error(errorStr))
  })
}

2.1 .cath capture

  console.log(1)

  await promiseSuccess().catch((error) => {
    
    
    console.log(error)
  })
  console.log(2)

  await promiseFail().catch((error) => {
    
    
    console.log(error)
  })
  console.log(3)
  • Execute the above code, the result is
1
2
Error: 出错了
3

Usually we need it when an error occurs 中断代码执行, so we need to combine the resolve result to judge whether to interrupt the code. The correct way to write it is

  console.log(1)

  const result1 = await promiseSuccess().catch((error) => {
    
    
    console.log(error)
  })
  if (!result1) return
  console.log(2)

  const result2 = await promiseFail().catch((error) => {
    
    
    console.log(error)
  })
  if (!result2) return
  console.log(3)
  • Execute the above code, the result is
1
2
Error: 出错了

2.2 try catch capture

The above code seems a bit long-winded, so we can use try catch, the correct code:

  try {
    
    
    console.log(1)
    const result1 = await promiseSuccess()
    console.log(2)
    const result2 = await promiseFail()
    console.log(3)
  } catch (error) {
    
    
    console.log(error)
  }
  • Execute the above code, the result is
1
2
Error: 出错了

3. Use return in the Promise method

First of all, it is not recommended to use return in the Promise method. If eslint is used, it will be prompted no-return-await. Let's see what the result will be if we use return

3.1 Pre-return

  • Modify the method promiseSuccess, it will resolve前execute return
/** promise成功 */
function promiseSuccess() {
    
    
  return new Promise((resolve) => {
    
    
    return 'return'
    resolve(true)
  })
}
  • test program
console.log(1)

const result = await promiseSuccess().catch((error) => {
    
    
  console.log(error)
})
console.log('result', result)
if (!result) return

console.log(2)
  • Execute the above code, the result is
1
  • Cause analysis: Since promiseSuccess has not been executed to resolve, await has been waiting, and the program will not continue processing.

3.2 post return

  • Modify the method promiseSuccess, it will resolve后execute return
/** promise成功 */
function promiseSuccess() {
    
    
  return new Promise((resolve) => {
    
    
    resolve(true)
    return 'return'
  })
}
  • The test program is set to be consistent with the above
  • Execute the above code, the result is
1
result true
2
  • Reason analysis: await只会获取resolve结果,里面的return值并没有影响.

Do not follow promise after four awaits

await is not only used to wait for Promise objects, it can wait for the result of any expression, so, after await, it can actually be followed by ordinary function calls or direct quantities. Wait for this operation to complete before proceeding to the program below the await statement.

The await is not followed by a promise object, and other values ​​will be wrapped into a promise object

(async function(){
    
    
  const res = await 400 //Promise.resolve(400)
  console.log(res) //400
})()

Await is followed by a normal function to receive the return value (it can be an asynchronous function)

(async function(){
    
    
	const res = await getData(false) // 这里会等待getData函数执行完毕,接收return值
})()

async function getData(param){
    
    
	if(param) return 1
	const res = await otherFun()
	return res
}

四 no-async-promise-executor

It is not recommended to pass the async function to the constructor of new Promise;
if the following code is useful, eslint will prompt no-async-promise-executor, because async is inherently asynchronous, so there is no need to nest it in Promise.

  • code example
// 错误示范:
function promiseTest() {
    
    
  return new Promise(async (resolve) => {
    
    
    const result = await promiseSuccess()
    resolve(result)
  })
}

// 正确示范1:
async function promiseTest() {
    
    
  const result = await promiseSuccess()
  return result
}

// 正确示范2,如果硬要使用Promise,那么可以这样:
async function promiseTest() {
    
    
  const result = await promiseSuccess()
  return new Promise((resolve) => {
    
    
    resolve(result)
  })
}
  • use the same way
const result1 = await promiseTest().catch((error) => {
    
    
  console.log(error)
})
console.log('result1', result1)

五、no-await-in-loop

It is not recommended to use await in the loop. This kind of writing usually means that the program does not take full advantage of JavaScript's event-driven.
Usually Promise.all can be used instead.

  • Sample code:
// 错误示范:
async function foo(things) {
    
    
  const results = [];
  for (const thing of things) {
    
    
    results.push(await bar(thing));
  }
  return baz(results);
}

// 正确示范:
async function foo(things) {
    
    
  const results = [];
  for (const thing of things) {
    
    
    results.push(bar(thing));
  }
  return baz(await Promise.all(results));
}

但是,如果每一次循环都需要改变数据,并且这个数据会带入到下次循环里,这种情况是可以使用循环里嵌套await的!

Guess you like

Origin blog.csdn.net/iamlujingtao/article/details/129177624