浅谈Promise对象在ReactNative中的使用

下面开始:

写在前面

假设现在一个日常开发会遇到这样一个需求:多个接口异步请求,第二个接口依赖于第一个

接口执行完毕之后才能利用数据进行一系列操作。一般会这样写:

            A.fetchData({
                url: 'http://......',
                success: function (data) {
                    A.fetchData({
                        // 要在第一个请求成功后才可以执行下一步
                        url: 'http://......',
                        success: function (data) {
                             // ......
                        }
                    });
                }
            });

这样写没问题,但是有两个缺点:


1、当有多个操作的时候,会导致多个回调函数嵌套,不够美观


2、如果有几个操作没有前后顺序之分时,例如上面的后一个请求不依赖与前一个请求的返回结果的时候,

同样也需要等待上一个操作完成再实行下一个操作。


从ES6开始,Promise对象可以解决上述问题。

什么是Promise对象

一个Promise对象可以理解为一次将要执行的操作,使用了Promise对象之后可以用一种链式调用的方式

来组织代码,让代码更加直观。

resolve和reject

先看代码:

  function helloWorld (ready) {
    return new Promise(function (resolve, reject) {
        if (ready) {
            resolve("Hello World!");
        } else {
            reject("Good bye!");
        }
    });
  }

    helloWorld(true).then(function (message) {
        alert(message);
    }, function (error) {
        alert(error);
    });

上面的代码实现的功能非常简单,helloWord 函数接受一个参数,如果为 true 就打印 "Hello World!",

如果为 false 就打印错误的信息。helloWord 函数返回的是一个 Promise 对象。


在 Promise 对象当中有两个重要方法————resolve 和 reject。


resolve 方法可以使 Promise 对象的状态改变成成功,同时传递一个参数用于后续成功后的操作,

在这个例子当中就是 Hello World! 字符串。


reject 方法则是将 Promise 对象的状态改变为失败,同时将错误的信息传递到后续错误处理的操作。

then

Promise 对象有三种状态:
1.Fulfilled 可以理解为成功的状态
2.Rejected 可以理解为失败的状态
3.Pending 既不是 Fulfilld 也不是 Rejected 的状态,可以理解为 Promise 对象实例创建时候的初始状态。


helloWorld 的例子中的 then方法就是根据 Promise 对象的状态来确定执行的操作,resolve 时执行第一个

函数(onFulfilled),reject 时执行第二个函数(onRejected)。promise模式在任何时刻都处于以下三种状态之一:未完成(unfulfilled)、已完成(resolved)和拒绝(rejected)。以CommonJS Promise/A 标准为例,promise对象上的then方法负责添加针对已完成和拒绝状态下的处理函数。then方法会返回另一个promise对象,以便于形成promise管道,这种返回promise对象的方式能够支持开发人员把异步操作串联起来,如then(resolvedHandler, rejectedHandler); 。resolvedHandler 回调函数在promise对象进入完成状态时会触发,并传递结果;rejectedHandler函数会在拒绝状态下调用。

示例代码1:

function printHello (ready) {
  var promise = new Promise(function (resolve, reject) {
      if (ready) {
          resolve("Hello");
      } else {
          reject("Good bye");
      }
  });
  return promise;
}

function printWorld () {
    console.log('World');
}

function printExclamation () {
    console.log('!!!');
}

 printHello(true)
 .then(function(message)
 .then(printWorld)
 .then(printExclamation)
 .catch(function(error){
    console.log(error);
  });;

函数先执行printHello,返回一个promise对象,通过then将异步操作串联起来。
执行结果应该是 Hello
World
!!!

示例代码2:

  function helloWorld (ready) {
    return new Promise(function (resolve, reject) {
        if (ready) {
            resolve("Hello World!");
        } else {
            reject("Good bye!");
        }
    });
  }

  var _this = this;
  printHello(true)
  .then(function (message) {
  var REQUEST_URL = 'https://raw.githubusercontent.com/facebook/react-native/master/docs/MoviesExample.json';
   return  fetch(REQUEST_URL)
      .then((response) => response.json())
      .then((responseData) => {
        var movie = responseData.movies[1];
        console.log('data   =   ', movie.title);
        return movie.title;
      })
  },function (error) {
      return(error);
  }).then(function (message) {
      return message  + ' World';
  }).then(function (message) {
      return message + '!!!';
  }).then(function (message) {
     console.log(message);
     console.log('finally');
  }).catch(function(error){
     console.log(error);
  });

上面的代码中有两个promise,第一个promise执行完毕后也就是printHello之后,会执行下一个then,

这个then返回了一个获取数据的promise,后面的then拿到的promise都是指向这个promise对象的。上述例子通过链式调用的方式,按顺序打印出了相应的内容。then 可以使用链式调用的写法原因在于,每一次执行该方法时总是会返回一个 Promise 对象。另外,在 then onFulfilled 的函数当中的返回值,可以作为后续操作的参数。

catch

catch 方法是 then(onFulfilled, onRejected) 方法当中 onRejected 函数的一个简单的写法,也就是说

可以写成 then(fn).catch(fn),相当于 then(fn).then(null, fn)。使用 catch 的写法比一般的写法更加清晰明确。

新手使用容易犯的错误
1.忘记添加catch()方法

这是一个很常见的错误。很多程序员对他们代码中的promise调用十分自信,觉得代码永远不会抛出一个 error ,

也可能他们只是简单的忘了加 catch() 方法。不幸的是,不加 catch() 方法会让回调函数中抛出的异常被吞噬,

在你的控制台是看不到相应的错误的,这对调试来说是非常痛苦的。

为了避免这种糟糕的情况,我已经养成了在自己的promise调用链最后添加如下代码的习惯:

      somePromise().then(function () {
        return aPromise();
      }).then(function () {
        return anotherPromise();
      }).catch(function(error){
               console.log(error);
            });

即使你并不打算在代码中处理异常,在代码中添加 catch() 也是一个谨慎的编程风格的体现。在某种情况下

你原先的假设出错的时候,这会让你的调试工作轻松一些。

2.return的混淆乱用

在then方法内部,我们可以做三件事:
1.return 一个promise对象
2.return一个同步的值或者是 undefined
3.同步的 throw 一个错误

理解这三种情况之后,你就会理解promise了。

1.返回另一个promise对象


在有关promise的相关文章中,这种写法很常见,就像上文提到的构成promise链的一段代码:

        getUserByName('nolan').then(function (user) {

          return fetch(REQUEST_URL)
                .then((response) => response.json())
                .then((responseData) => {

                 }        

        }).then(function () {
        });

2.返回一个具体的值或者是 undefined

    getUserByName('nolan').then(fcuntion (user) {
        if (inMemoryCache[user.id]) {
            return inMemoryCache[user.id];  
            // returning a value!
        }
        return inMemoryCache[user.id];
         // returning a promise
    }).then(function (userAccount) {
        // I got a user account
    })

如果不调用return语句的话,javaScript里的函数会返回 undefined 。这也就意味着在你想返回一些值的时候,

不显式调用return会产生一些副作用。

出于上述原因,养成了一个个人习惯就是在then方法内部永远显式的调用return或者throw。我也推荐你这样做。

3.抛出一个错误

说到throw,这又体现了promise的功能强大。在用户退出的情况下,我们的代码中会采用抛出异常的方式进行处理:

    getUserByName('nolan').then(function (user) {
      if (user.isLoggedOut()) {
        throw new Error('user logged out!'); 
        // throwing a error!
      }
      if (inMemoryCache[user.id]) {
        return inMemoryCache[user.id];      
         // returning a value!
      }
      return getUserAccountById(user.id);   
       // returning a promise!
    }).then(function (userAccount) {
      // I got a user account!
    }).catch(function (err) {
      // Boo, I got an error!
    });

如果用户已经登出的话, catch() 会收到一个错误,如果有promise对象的状态变为rejected的话,

它还会收到一个错误。


在使用promise的时候抛出异常在开发阶段很有用,它能帮助我们定位代码中的错误。比方说,

在then函数内部调用 JSON.parse() ,如果JSON对象不合法的话,可能会抛出异常,在回调函数中,这个异常会被吞噬,但是在使用promise之后,我们就可以捕获到这个异常了。



作者:梅庆
链接:http://www.jianshu.com/p/174d9892283f
來源:简书

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值