创建Promise
Promise
对象是由关键字 new
及其构造函数来创建的。该构造函数会把一个叫做“处理器函数”(executor function)的函数作为它的参数。这个“处理器函数”接受两个函数——resolve
和 reject
——作为其参数。当异步任务顺利完成且返回结果值时,会调用 resolve
函数;而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用reject
函数。
const myFirstPromise = new Promise((resolve, reject) => { // ?异步操作,最终调用: // // resolve(someValue); // fulfilled // ?或 // reject("failure reason"); // rejected });
想要某个函数拥有promise功能,只需让其返回一个promise即可
function myAsyncFunction(url) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open("GET", url); xhr.onload = () => resolve(xhr.responseText); xhr.onerror = () => reject(xhr.statusText); xhr.send(); }); };
示例:
let myFirstPromise = new Promise(function (resolve, reject) { // 当异步代码执行成功时,我们才会调用resolve(...), 当异步代码失败时就会调用reject(...) // 在本例中,我们使用setTimeout(...)来模拟异步代码,实际编码时可能是XHR请求或是HTML5的一些API方法. setTimeout(function () { resolve('成功!') // 代码正常执行! }, 250) }) myFirstPromise.then(function (successMessage) { // successMessage的值是上面调用resolve(...)方法传入的值. // successMessage参数不一定非要是字符串类型,这里只是举个例子 console.log('Yay! ' + successMessage) })
控制台输出打印的是 Yay! 成功!
例子:
用户注册之前需要填入正确的手机验证码。在用户信息都填入完整之后点击注册时还需校验验证码是否填写正确
// 验证验证码 export function validCode (param) { return fdcJsonp(process.env.API_CODE, 'picgif.oauth.sms.verifycode', param) .then(res => { if (res.code === '200') { return res } }) .catch((err) => { return Promise.reject({ code: 'code.has.error', msg: err }) }) }
// 用户注册 export function registUser (params) { return fdcJsonp(process.env.API_ROOT_UC, 'ucaction.user.adduserbymobile', params) .then((res) => { return res }) .catch((err) => { return Promise.reject({ code: 'registed.has.failed', msg: err }) }) }
校验注册代码逻辑如下:
validCode({ code: this.code, mobile: this.phone }) .then((res) => { if (res.code === '200') { if (this.isRegistering) { return } this.isRegistering = true this.$refs.registBtn.innerHTML = '正在注册...' return registUser({ loginName: this.userName, mobileNum: this.phone, userPasswd: this.password, verifyCode: this.code, v: '2.0', userid: Cookie.get('uc_userInfo') registerFrom: getRegFrom(curUrl) }) } }) .then((res) => { let instance = Toast.success('注册成功') setTimeout(() => { instance.close() this.$router.push('/') }, 2000) }) .catch((err) => { if (err.code) { switch (err.code) { case 'code.has.error': case 'registed.has.failed': Toast(err.msg) break } } this.btnName = '注册' this.registerAllow = true })
一个 Promise
就是一个代表了异步操作最终完成或者失败的对象. 一个promise可以使用它的constructor创建。然而,大多数人都在使用由其他函数创建并返回的promise。
promise替代了下面这种旧式的函数,这种旧式函数需要两个回调函数,并最终调用处理成功事件或者处理失败事件的回调函数:
function successCallback(result) { console.log("It succeeded with " + result); } function failureCallback(error) { console.log("It failed with " + error); } doSomething(successCallback, failureCallback);
新式函数返回一个你可以直接绑定回调函数的promise对象,来代替旧式的函数形式:
let promise = doSomething();
promise.then(successCallback, failureCallback);
或者更简单的形式:
doSomething().then(successCallback, failureCallback);
不像旧式函数那样传递回调函数,promise会带来一些保证:
- 在JavaScript事件队列的当前运行完成之前,回调函数永远不会被调用。
- 通过.then形式添加的回调函数,甚至都在异步操作完成之后才被添加的函数,都会被调用,如上所示。
- 通过多次调用.then,可以添加多个回调函数,它们会按照插入顺序并且独立运行。
但是,promise最直接的好处就是链式调用。
通过现代的函数,我们把回调附加到被返回的promise上代替以往的做法,形成一个promise chain:
doSomething().then(function(result) { return doSomethingElse(result); }) .then(function(newResult) { return doThirdThing(newResult); }) .then(function(finalResult) { console.log('Got the final result: ' + finalResult); }) .catch(failureCallback);
then里的参数是可选的,catch(failureCallback)
是 then(null, failureCallback)
的缩略形式。如下所示,也可以用 箭头函数来表示:
doSomething() .then(result => doSomethingElse(result)) .then(newResult => doThirdThing(newResult)) .then(finalResult => { console.log(`Got the final result: ${finalResult}`); }) .catch(failureCallback);
注意:一定要返回promise,不然的话回调不会形成链式,错误也获取不到(当省略{}时,箭头函数将隐式返回)。
当异步代码执行成功时,我们才会调用resolve(...), 当异步代码失败时就会调用reject(...)。
是