资讯专栏INFORMATION COLUMN

Promise快餐

leone / 2210人阅读

摘要:实例具有方法方法是定义在原型对象上的它的作用是为实例添加状态改变时的回调函数。一个请求的例子出错了方法是的别名,用于指定发生错误时的回调函数。那个率先改变的实例的返回值,就传递给的回调函数。

Promise 是异步编程的一种解决方案,其他的异步编程解决方案还有——回调函数事件监听发布订阅,以及ES6新增的Generator

http://www.ruanyifeng.com/blo...
http://es6.ruanyifeng.com/#do...

Promise的状态

Pending(进行中)

Resolved (已完成)

Rejected (已失败)

Promise的特点

对象的状态不受外界影响。

一旦状态改变,就不会再变,任何时候都可以得到这个结果。

Promise的用法
var promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

注意:

resovle和reject函数都是由js引擎提供的函数不用自己定义。

其中 resovle函数的作用是将Promise对象从进行中状态转换为已完成reject函数将Promise对象从进行中状态转换为已失败状态。

Promise.prototype.then()

Promise 实例具有then方法,then方法是定义在原型对象Promise.prototype上的,它的作用是为 Promise 实例添加状态改变时的回调函数。

延续上面的代码:

promise.then(function(res) {
    console.log(res)
}, function(err) {
    console.log(err)
})

then对象接收两个回调函数作为参数,第一个回调函数是resovle的回调,第二个回调函数是reject的回调。即,一个用于处理状态为已完成的逻辑,另一个用于处理已失败的逻辑。

一个Ajax请求的例子:

var getJSON = function(url) {
  var promise = new Promise(function(resolve, reject){
    var client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();

    function handler() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
  });

  return promise;
};

getJSON("/posts.json").then(function(json) {
  console.log("Contents: " + json);
}, function(error) {
  console.error("出错了", error);
});
Promise.prototype.catch()

Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。不是指then方法的别名而是指resovle的回调函数为null的then方法的别名。

通常推荐使用catch方法来捕获异常,而不是使用reject的回调函数。

// 不推荐的写法
promise
  .then(function(data) {
    // success
  }, function(err) {
    // error
  });

// 推荐的写法
promise
  .then(function(data) {
    // success
  })
  .catch(function(err) {
    // error
  });

使用catch方法来接收错误信息的好处是,Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。所以一个catch可以捕获链式调用中多个Promise对象抛出的异常。

链式调用

当有几个异步操作需要链式调用时,promise是支持的。

一个简单的链式调用的例子:

getJSON("/post/1.json").then(function(post) {
  return getJSON(post.commentURL);
}).then(function funcA(comments) {
  console.log("Resolved: ", comments);
}, function funcB(err){
  console.log("Rejected: ", err);
});

Promise的then函数,返回的是一个新的Promise对象。如果返回的对象不是Promise对象会是什么效果呢?
以下是一些测验代码:

var promise = new Promise(function(resolve, reject) {
  let a = "111";
    resolve(a);
});

promise.then(function(res) {
    return null;
}).then(function(res){
    console.log(res);
}).catch(function(err) {
    console.log(err);
})
// null
var b = function() {
    console.log("bb");
}

var promise = new Promise(function(resolve, reject) {
  let a = "111";
    resolve(a);
});

promise.then(function(res) {
    return b();
}).then(function(res){
    console.log(res);
})
// bb
// undefined

可以看出,如果then retrun的不是一个Promise函数时,并不会报错,也没有抛出异常,相当于一个没有执行reject和resovle的Promise对象(个人理解,有失偏颇。望自慎重,择善从之。)。

Promise.all()

在某些时候,我们需要执行多个异步操作。这些异步操作可能有以下几种关系:

互不关联

逐个依赖

部分依赖

结果依赖(指需要获得所以返回的结果进行下一步的操作)

Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。可以用来解决上面的4关系。
互不关联最好分开调用,部分依赖、逐个依赖用链式调用。

Promise.all接收一个Promise数组作为参数,即数组中的值都是Promise对象,如果不是就会先调用Promise.resovle方法,将参数转为Promise实例。

// 生成一个Promise对象的数组
var promises = [2, 3, 5, 7, 11, 13].map(function (id) {
  return getJSON("/post/" + id + ".json");
});

Promise.all(promises).then(function (posts) {
  // ...
}).catch(function(reason){
  // ...
});

只有当所有的Promise对象都返回resovle时才会执行then方法,只要有一个Pormise对象返回的是reject,就执行catch。

ps: 还有Promise.race()方法,此方法和Promise.all()不同之处时,只要传入的Promise数组中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。可用于限制请求的最大反应时间。

const p = Promise.race([
  fetch("/resource-that-may-take-a-while"),
  new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error("request timeout")), 5000)
  })
]);
p.then(response => console.log(response));
p.catch(error => console.log(error));
// 如果超过5秒就返回请求超时
Promise.resolve()和Promise.reject()

这两个方法返回一个新的Promise实例,resovle方法返回的实例状态为resolve,同理reject方法返回reject。
都接收一个参数作为现有的对象,此参数可以为任何值包括null,undefined。
根据接收的参数,两种方法都会做出不同的处理。在此不做详细的介绍了,有兴趣的可以去看看

http://es6.ruanyifeng.com/#do...

Promise.resolve("foo")
// 等价于
new Promise(resolve => resolve("foo"))
finally()

此方法用于最后执行,不Promise的状态如何,都会执行的操作(还有这种操作?)。在node中可用于关闭服务器或者数据库连接。在浏览器中可用于需要在异步函数返回之后执行的操作。

var p = new Promise(function(resovle.reject){
    resovle("is resovle");
});

p.then(function(res) {
    console.log(res) 
}).finally(function() {
    console.log("is finally");
})

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/83664.html

相关文章

  • [译] 深入理解 Promise 五部曲:2. 控制权转换问题

    摘要:直到最近,我们仍然在用简单的回调函数来处理异步的问题。当我们只有一个异步任务的时候使用回调函数看起来还不会有什么问题。 原文地址:http://blog.getify.com/promis... 厦门旅行归来,继续理解Promise 在上一篇深入理解Promise五部曲:1.异步问题中,我们揭示了JS的异步事件轮询并发模型并且解释了多任务是如何相互穿插使得它们看起来像是同时运行的。...

    alanoddsoff 评论0 收藏0
  • ES2017异步函数现已正式可用

    摘要:标准已于年月份正式定稿了,并广泛支持最新的特性异步函数。为了领会,我们需要回到普通回调函数中进一步学习。从此编写回调函数不再那么痛苦。回调是一个函数,可以将结果传递给函数并在该函数内进行调用,以便作为事件的响应。 ES2017标准已于2017年6月份正式定稿了,并广泛支持最新的特性:异步函数。如果你曾经被异步 JavaScript 的逻辑困扰,这么新函数正是为你设计的。 异步函数或多或...

    android_c 评论0 收藏0
  • Tensorflow快餐教程(5) - 范数

    摘要:当时,范数称为欧几里得范数。更严格地说,范数是满足下列性质的任意函数这条被称为三角不等式范数的推广除了范数之外,在机器学习中还常用范数,就是所有元素的绝对值的和。 摘要: 范数的定义和Tensorflow实现 矩阵进阶 - 范数 作为快餐教程,我们尽可能多上代码,多介绍工具,少讲原理和公式。但是我也深知这样是无法讲清楚的,毕竟问题的复杂度摆在这里呢。与大家一起在Tensorflow探索...

    RancherLabs 评论0 收藏0

发表评论

0条评论

leone

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<