JavaScript ES6入门教程:13.promise



promise

Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。Promise 是异步编程的一种解决方案,比回调函数和事件更合理更强大。使用Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。

用法

const promise = new Promise(function(resolve, reject) {
  // ... some code

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

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供。resolve函数在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
注意:Promise 新建后就会立即执行。一般来说,并不需要它立即执行,应该是在需要的时候调用它,然后执行。所以,用Promise的时候一般是包在一个函数中,在需要的时候去运行这个函数,如:

function runPromise(){
    const promise = new Promise(function(resolve, reject) {
  // ... some code

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

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

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

第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。

function runPromise(data){
	var promise = new Promise(function(resolve,reject){
		setTimeout(()=>{console.log("任务一");resolve(data)},2000)	
	});
	return promise
}
runPromise("想传递的数据").then(function(data){
	console.log(data);
})
//任务一
//想传递的数据

链式调用

Promise 实例具有then方法,为 Promise 实例添加状态改变时的回调函数。返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法:

function runPromise(task,data){
	var promise = new Promise(function(resolve,reject){
		setTimeout(()=>{console.log(task);resolve(data)},2000)	
	});
	return promise
}
runPromise("任务1","想传递的数据1").then(function(data){
	console.log(data);
	return runPromise("任务2","想传递的数据2")
}).then(function(data){
	console.log(data)
})
//任务1
//想传递的数据1
//任务2
//想传递的数据2

也可以直接return数据而不是Promise对象,这样后面的then中就可以只接收数据。

错误处理

Promise对象除了then方法,还有一个catch方法来处理错误,效果和写在then的第二个参数里面一样。另外,在执行resolve的回调时,如果代码出错了,那么并不会报错卡死js,而是会进到这个catch方法中:

runPromise("任务1","想传递的数据1").then(function(data){
	console.log(data);
	console.log(error)
}).catch(function(reason){
	console.log(reason)
})
//任务1
//想传递的数据1
//ReferenceError: error is not definedat test.html:71

Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。因此,不需要在then方法里面定义 Reject 状态的回调函数(即then的第二个参数),只需要在多个then方法最后添加catch方法就可以。

ajax

用Promise对象实现的 Ajax 操作的例子:

const getJSON = function(url) {
  const promise = new Promise(function(resolve, reject){
    const handler = function() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
    const client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();

  });

  return promise;
};

getJSON("/example.json").then(function(json) {
  console.log('Contents: ' + json);
}, function(error) {
  console.error('出错了', error);
});

上一篇: 11.set和map 下一篇: 14.class