Promise实际操演

Promise

JavaScript 是属于同步的程式语言,因此一次仅能做一件事情,但遇到非同步的事件时,就会将非同步的事件移动到程式码的最后方,等到所有的原始码运行完以后才会执行非同步的事件。

以下列的程式码来说,在 console 中依序的会出现的顺序为:

开始结束非同步事件 <- 最后执行
console.log('开始');setTimeout(() => {  console.log('非同步事件');}, 0);console.log('结束');

虽然在上段的原始码中,setTimeout 所定义的时间为 0,但因为是属于非同步事件,因此还是会在其他原始码运行完以后才执行。

我们再axios文件中找一段实际範例参考,先定义一个data物件,中间段落使用 axios 尝试取得远端资料,后面的紧接的 console.log(data),实际测试看看console的结果是什么?

你应该会觉得concole顺序依序为:

"开始执行"'/user?ID=12345"测试有没有接收到资料"
let data = {}console.log('开始执行');const api = '/user?ID=12345'axios.get(api).then(response => {  data = response;  console.log('测试有没有接收到资料');});console.log(data);

其实正确的 console 中依序的会出现的顺序是:

"开始执行"[object Object] { ... }"测试有没有接收到资料"

你应该会想说为什么console.log(data)会没有接收到资料呢?
因为上述的非同步行为,导致api还尚未接收到,因此才会出现[object]

实战演练Promise,以Vue为範例

一、数字题型:

const app = new Vue({  el: '#app',  created() {    this.promise(100)      .then(success => {        console.log(success);        return this.promise(1000);      })      .then(success => {        console.log(success);        return this.promise(0); // 这个阶段会进入 catch      })      .then(success => {   // 由于上一个阶段结果是 reject,所以此段不执行        console.log(success);        return this.promise('Hello');      })      .catch(error => {        console.log(error);      })  },  methods: {    promise (num) {      return new Promise((resolve, reject) => {        num ? resolve('成功') : reject('失败');      });     }   }, })

因此console出来的结果为:

成功成功失败

二、JSON Data一般题型:
将题型一的值更改为JSON,分别为apiA以及apiB
可将此段程式码複製贴到开发者工具看有没有什么不同的地方~

const app = new Vue({  el: '#app',    created () {    const apiA = 'https://data.taipei/api/v1/dataset/80ab7634-dabd-4012-be8c-fb7da0101e9b?scope=resourceAquire'    const apiB = 'https://data.taipei/api/v1/dataset/36847f3f-deff-4183-a5bb-800737591de5?scope=resourceAquire'    this.demo(apiA).then(res => {      console.log(res)      return this.demo(apiB)    }).then(res => {      console.log(res)    }).catch(err => {      console.log(err)    })  },  methods: {    demo (api) {      return new Promise((resolve, reject) => {        axios.get(api).then((res) => {          const data = res.data.result.results          res.status === 200 ? resolve(data) : reject('error api')        })      })    }  }})

三、进阶题型:
使用indexOf去寻找哪个api中有符合80ab7634的字串,有的话则会执行setTimeout延迟5秒!
然而,在这个範例中indexOf寻找到apiA有符合,但是js是由上到下去执行的,因此js会等待apiA回传回来后,接着马上跟着回传apiB,因此apiA与apiB都将延迟5秒回传

const app = new Vue({  el: '#app',  created() {    const apiA = 'https://data.taipei/api/v1/dataset/80ab7634-dabd-4012-be8c-fb7da0101e9b?scope=resourceAquire'    const apiB = 'https://data.taipei/api/v1/dataset/36847f3f-deff-4183-a5bb-800737591de5?scope=resourceAquire'    this.demo(apiA).then(res => {      console.log(res);      return this.demo(apiB)    }).then(res => {      console.log(res);    }).catch(err => {      console.log(err);    })  },  methods: {    demo(api) {      return new Promise((resolve, reject) => {        axios.get(api).then((res) => {          if (res.status === 200) {            if (api.indexOf('80ab7634') > -1) {              setTimeout(() => {                resolve(res.data)              }, 5000)            } else {              resolve(res.data)            }          } else {            reject('error api')          }        })      })    },  },})

假如我们将indexOf的值变更为36847f3f,猜猜看会出现什么有趣的事呢?
这时会发现,js先回传apiA,经过了5秒后才会回传apiB
因为js未搜寻到apiA有36847f3f的值,因此不会去执行setTimeOut

const app = new Vue({  el: '#app',  created() {    const apiA = 'https://data.taipei/api/v1/dataset/80ab7634-dabd-4012-be8c-fb7da0101e9b?scope=resourceAquire'    const apiB = 'https://data.taipei/api/v1/dataset/36847f3f-deff-4183-a5bb-800737591de5?scope=resourceAquire'    this.demo(apiA).then(res => {      console.log(res);      return this.demo(apiB)    }).then(res => {      console.log(res);    }).catch(err => {      console.log(err);    })  },  methods: {    demo(api) {      return new Promise((resolve, reject) => {        axios.get(api).then((res) => {          if (res.status === 200) {            if (api.indexOf('36847f3f') > -1) {              setTimeout(() => {                resolve(res.data)              }, 5000)            } else {              resolve(res.data)            }          } else {            reject('error api')          }        })      })    },  },})

希望藉由上述三个不同的简单实例,能让大家更了解Promise的运作模式


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章