1、JavaScript Promise介绍
在JS代码中,Promise到底有什么作用?
首先,我们知道的是,Javascript是单线程的,什么意思呢?就是说JS在同一时间只能做一个操作,代码的执行是一行一行进行的:
这种执行方式带来的问题就是在我们打开某个画面的时候,画面可能会卡住转圈、加载中状态很久,用户体验感很差。
Promise可用于资源加载或异步操作,于是,用Promise方法便能解决这个问题。
以下,是使用Promise的方法例图(图片来自于网络):
上图对应代码如下:
let shouldBeResolve = true;
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldBeResolve) {
resolve('success!');
}
reject('failed!');
}, 1000);
});
// then/catch
const thenCatchApproach = () => {
promise
.then((result) => {
console.log(`thenCatchApproach result => ${result}.`);
})
.catch((error) => {
console.log(`thenCatchApproach error => ${error}.`);
})
.finally(() => {
console.log('thenCatchApproach done.');
})
}
// async/await
const asyncAwaitApproach = async () => {
try {
const result = await promise;
console.log(`asyncAwaitApproach result => ${result}.`);
} catch (error) {
console.error(error);
console.log(`asyncAwaitApproach error => ${error}.`);
} finally {
console.log('asyncAwaitApproach done.');
}
}
// success
shouldBeResolve = true;
thenCatchApproach();
asyncAwaitApproach();
Promise主要有以下三种状态:
- pending: 初始状态
- fulfilled: 意味着操作执行成功
- rejected: 意味着操作失败
同时,由上图可看出,then/catch和async/await非常相似,都可以用来解决Promise问题。
那么,两者有什么区别呢?
使用async/await将暂停函数执行,直到Promise有结果(resolve或者reject)。因此,此异步行为表现得有点像同步。
function myPromiseFunction() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Success');
}, 2000);
});
}
(async () => {
console.log('Start');
const result = await myPromiseFunction();
console.log(`result - ${result}`);
console.log('End');
})();
而then/catch则是将继续执行逻辑,直到Promise有结果JS将会执行then()方法回调。
function myPromiseFunction() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Success');
}, 2000);
});
}
(() => {
console.log('Start');
myPromiseFunction()
.then(result => {
console.log(`result - ${result}`);
})
.catch(error => {
console.error(error);
})
console.log('End');
})();
2、Salesforce LWC中Promise的使用情况
在LWC中,所有的Apex方法都返回一个Promise对象。
import apexMethodName from '@salesforce/apex/Namespace.Classname.apexMethodReference';
我们可以通过三种方式使用上述apex方法:
- @wire
- Then/Catch
- Async/Await
2-1、Wire
使用场景:
- 返回的数据结果可以被缓存,@wire的apex方法需要被标记为(Cacheable=true)
- @wire只可以用来读取数据,不支持DML操作(insert,update,delete)
对于一个属性:
import apexMethodName from '@salesforce/apex/Namespace.Classname.apexMethodReference'; @wire(apexMethodName, { apexMethodParams }) property;
对于一个方法:
import apexMethodName from '@salesforce/apex/Namespace.Classname.apexMethodReference';
@wire(apexMethodName, { apexMethodParams })
wiredFunction({ error, data }) {
if (data) {
console.log(data);
} else if (error) {
console.error(error);
}
}
2-2、Then/Catch
使用场景:
- 需要对数据库进行DML操作(insert,update,delete)
- 数据不能被缓存
- 应该用户操作(如onclick事件)后调用该apex方法
import apexMethodName from '@salesforce/apex/Namespace.Classname.apexMethodReference';
apexMethodName
.then(result => {
console.log(result);
})
.catch(error => {
console.error(error);
})
.finally(() => {
console.log('done.'); //good place to hide spinner
})
2-3、Async/Await
使用场景:
- 需要对数据库进行DML操作(insert,update,delete)
- 数据不能被缓存
- 应该用户操作(如onclick事件)后调用该apex方法
- 代码应该表现为同步
import apexMethodName from '@salesforce/apex/Namespace.Classname.apexMethodReference';
try {
let result = await apexMethodName;
} catch (error) {
console.error(error);
} finally {
console.log('done.'); //good place to hide spinner
}
多个await链式执行
import { LightningElement } from 'lwc';
import apexMethod1 from '@salesforce/apex/ClassName.apexMethod1';
import apexMethod2 from '@salesforce/apex/ClassName.apexMethod2';
import apexMethod3 from '@salesforce/apex/ClassName.apexMethod3';
export default class LwcPromise extends LightningElement {
connectedCallback() {
this.invokeApexMethods();
}
async invokeApexMethods() {
try {
const result1 = await apexMethod1();
const result2 = await apexMethod2({ param: result1 });
const result3 = await apexMethod3({ param: result2 });
} catch(error) {
console.error(error);
} finally {
console.log('Finally Block');
}
}
}
Async/Await总结:
异步方法总会返回一个Promise对象。Await只能被用在被标记为async(异步)的方法里。
Copyright © 乔木船长
个人主页:乔木船长
欢迎转发点评和指正!