weex之Promise

2019-04-29  本文已影响0人  猪猪行天下

Promise的含义

promise是异步编程的一种解决方法,比传统的回调函数和事件更合理更强大
。promise里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果,从语法上说,promise是一个对象,从它可以获取异步操作的消息,promise提供了统一的API,各种异步操作都可以用同样的方法进行处理。

Promise优缺点

flow.png

Promise实例

使用构造函数创建一个promise对象实例

var promise = new Promise( function( resolve, reject) {
       //异步操作成功 
      if(value){
             resolve(value);
       }else{
         reject(error);
       }
});

参数:resolve和reject,是两个函数,由Javascript引擎提供,不用自己部署。
resolve函数的作用:将promise对象的状态从“pending”变为‘’resolved‘’,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;

reject函数的作用是:将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数,使用如下:

promise.then(
    function(value){
        //success
   },
    function(error){
        //failure
 });

then()方法回调函数说明:

如果调用resolve函数和reject函数时带有参数,那么他们的参数会被传递给回调函数,reject函数的参数通常是Error对象的实例,表示抛出的错误,resolve函数的参数除了正常的值以外,还可以是另一个promise实例;

var p1 = new Promise(function (resolve, reject) {
  // ...
});

var p2 = new Promise(function (resolve, reject) {
  // ...
  resolve(p1);
})

p1和p2都是 Promise 的实例,但是p2的resolve方法将p1作为参数,即一个异步操作的结果是返回另一个异步操作。
这时p1的状态就会传递给p2,也就是说,p1的状态决定了p2的状态。如果p1的状态是pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是resolved或者rejected,那么p2的回调函数将会立刻执行。

Promise执行顺序问题

看下这段代码输入:

let promise = new Promise(function(resolve, reject) {
  console.log('Promise');
  resolve();
});

promise.then(function() {
  console.log('resolved.');
});

console.log('Hi!');

// Promise
// Hi!
// resolved

Promise新建后就会立即执行,所以首先输出的是Promise。然后,then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以resolved最后输出。

注意,调用resolve或reject并不会终结 Promise 的参数函数的执行

new Promise((resolve, reject) => {
  resolve(1);
  console.log(2);
}).then(r => {
  console.log(r);
});
// 2
// 1

调用resolve(1)以后,后面的console.log(2)还是会执行,并且会首先打印出来。这是因为立即 resolved 的 Promise 是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。
一般来说,调用resolve或reject以后,Promise 的使命就完成了,后继操作应该放到then方法里面,而不应该直接写在resolve或reject的后面。所以,最好在它们前面加上return语句,这样就不会有意外。

new Promise((resolve, reject) => {
  return resolve(1);
  // 后面的语句不会执行
  console.log(2);
})

weex使用Promise

storage使用Promise

getItem: function(key) {
        const storage = weex.requireModule("storage");
        return new Promise(function(resolve, reject) {
            try {
                storage.getItem(key, e => {
                    if (e.result === 'success') {
                        resolve(e);
                    } else {
                        console.log('获取本地数据失败')
                        reject(e);
                    }
                });
            } catch (e) {
                console.log('获取本地数据异常')
                let event = {
                    result: 'fail',
                }
                reject(event);
            }
        });
    }

使用时

getItem('key').then(r => {
    
});

网络请求

promise对象实现stream操作的例子

 post: function(url,param){
            var promise = new Promise( function(resolve,reject ) {
              const stream = weex.requireModule('stream');
                    var HTTPHeader = { 'Content-Type': 'application/json' }
                    var jsonType = 'text'
                    stream.fetch({
                        method: 'POST',
                        // timeout: 30000,//30s
                        url: url,
                        type: jsonType,
                        headers: HTTPHeader,
                         body: JSON.stringify(param)
                    }, function(ret){
                            if(!ret.ok){
                                let err = new Error('请求失败')
                                reject(err);
                            }else{
                                
                                resolve(ret.data);
                            }
                            
                    })
         });
         
            return promise;     
    }

发起请求

const body = {title:'标题', article:'内容'};
const API = 'https://jsonplaceholder.typicode.com/posts';
this.post(API,body).then(data =>{
       modal.alert({message:data})
       //{"title":"标题", "article":"内容","id":"101"}
 })
 

then()方法返回的是一个新的Promise实例(不是原来那个Promise实例),因此可以采用链式写法,即then方法后面再调用另一个then方法

post(url,param).then(function (respone){
           return respone;
}).then(function(data){
           //...
});

采用链式的then,可以指定一组按照次序调用的回调函数。这时前一个回调函数,有可能返回的还是一个promise对象(即有异步操作),这时后一个回调函数,就会等待该promise对象的状态发生变化,才会被调用。例如两个网络请求,第二个依赖于第一个请求返回的数据:

const self = this;
this.post(API,body).then(function(data){
       //{"title":"标题", "article":"内容","id":"101"}
       let objc = JSON.parse(data)
       let newBody = {title:objc.article,article:objc.title}
       return  self.post(API,newBody)
 }).then(function  funA(result) {
         console.log("resolved:" ,result);
}, function funB(err){
        console.log("rejected:", err);
})

上面第一个then方法指定的回调函数,返回的是另一个promise对象,这时,第二个then方法指定的回调函数,就会等待这个新的Promise对象状态发生变化。如果变为resolved,就调用funA,如果状态变为rejected,就调用funB。改为箭头函数,代码更简洁:

const self = this;
this.post(API,body).then(data => {
       //{"title":"标题", "article":"内容","id":"101"}
       let objc = JSON.parse(data)
       let newBody = {title:objc.article,article:objc.title}
       return  self.post(API,newBody)
 }).then(result => {
         console.log("resolved:" ,result);
}, err => {
        console.log("rejected:", err);
})

上一篇 下一篇

猜你喜欢

热点阅读