美文网首页
异步:Promise

异步:Promise

作者: 诺CIUM | 来源:发表于2018-12-17 17:28 被阅读5次

Promise 是一个对象,对象里存储一个状态,这个状态是可以随着内部的执行转化的,为以下三种状态之一:等待态(Pending)、完成态(Fulfilled)、拒绝态(Rejected)。

一开始,我们先设置好等状态从 pending 变成 fulfilled 和 rejected 的预案(当成功后我们做什么,失败时我们做什么)。

Promise 启动之后,当满足成功的条件时我们让状态从 pending 变成 fullfilled (执行 resolve);当满足失败的条件,我们让状态从 pending 变成 rejected(执行 reject)

Promise 方法

Promise.prototype.then / Promise.prototype.catch

如何生成一个promise对象

   function A(){
        return new Promise (function(x,y){
            setTimeout(()=>{
                x("hello")
            }, 3000)
        })
    }
    A().then((e)=>{
        console.log(e)  //"hello"
    })

链式调用

function getIp() {
  var promise = new Promise(function(resolve, reject){
    var xhr = new XMLHttpRequest()
    xhr.open('GET', 'https://easy-mock.com/mock/5ac2f80c3d211137b3f2843a/promise/getIp', true)
    xhr.onload = function(){
      var retJson = JSON.parse(xhr.responseText)  // {"ip":"58.100.211.137"}
      resolve(retJson.ip)
    }
    xhr.onerror = function(){
      reject('获取IP失败')
    }
    xhr.send()
  })
  return promise
}

function getCityFromIp(ip) {
  var promise = new Promise(function(resolve, reject){
    var xhr = new XMLHttpRequest()
    xhr.open('GET', 'https://easy-mock.com/mock/5ac2f80c3d211137b3f2843a/promise/getCityFromIp?ip='+ip, true)
    xhr.onload = function(){
      var retJson = JSON.parse(xhr.responseText)  // {"city": "hangzhou","ip": "23.45.12.34"}
      resolve(retJson.city)
    }
    xhr.onerror = function(){
      reject('获取city失败')
    }
    xhr.send()
  })
  return promise
}
function getWeatherFromCity(city) {
  var promise = new Promise(function(resolve, reject){
    var xhr = new XMLHttpRequest()
    xhr.open('GET', 'https://easy-mock.com/mock/5ac2f80c3d211137b3f2843a/promise/getWeatherFromCity?city='+city, true)
    xhr.onload = function(){
      var retJson = JSON.parse(xhr.responseText)   //{"weather": "晴天","city": "beijing"}
      resolve(retJson)
    }
    xhr.onerror = function(){
      reject('获取天气失败')
    }
    xhr.send()
  })
  return promise
}

getIp().then(function(ip){
  return getCityFromIp(ip)
}).then(function(city){
  return getWeatherFromCity(city)
}).then(function(data){
  console.log(data)
}).catch(function(e){
  console.log('出现了错误', e)
})

Promise.all

function getCityFromIp(ip) {
  var promise = new Promise(function(resolve, reject){
    var xhr = new XMLHttpRequest()
    xhr.open('GET', 'https://easy-mock.com/mock/5ac2f80c3d211137b3f2843a/promise/getCityFromIp?ip='+ip, true)
    xhr.onload = function(){
      var retJson = JSON.parse(xhr.responseText)  // {"city": "hangzhou","ip": "23.45.12.34"}
      resolve(retJson)
    }
    xhr.onerror = function(){
      reject('获取city失败')
    }
    xhr.send()
  })
  return promise
}

var p1 = getCityFromIp('10.10.10.1')
var p2 = getCityFromIp('10.10.10.2')
var p3 = getCityFromIp('10.10.10.3')

//Promise.all, 当所有的 Promise 对象都完成后再执行
Promise.all([p1, p2, p3]).then(data=>{
  console.log(data)
})

Promise.race

function getCityFromIp(ip) {
  var promise = new Promise(function(resolve, reject){
    var xhr = new XMLHttpRequest()
    xhr.open('GET', 'https://easy-mock.com/mock/5ac2f80c3d211137b3f2843a/promise/getCityFromIp?ip='+ip, true)
    xhr.onload = function(){
      var retJson = JSON.parse(xhr.responseText)  // {"city": "hangzhou","ip": "23.45.12.34"}
      resolve(retJson)
    }
    xhr.onerror = function(){
      reject('获取city失败')
    }
    setTimeout(()=>{
      xhr.send()
    }, Math.random()*1000)

  })
  return promise
}

var p1 = getCityFromIp('10.10.10.1')
var p2 = getCityFromIp('10.10.10.2')
var p3 = getCityFromIp('10.10.10.3')

//Promise.all, 当所有的 Promise 对象都完成后再执行
Promise.race([p1, p2, p3]).then(data=>{
  console.log(data)
})

作用:解决回调地狱,也就是多层嵌套回调函数问题

范例:

  • 实现: 1秒钟之后输出 fn1, 再过疫苗输出 fn2, 再过1秒输出 fn3
//回调函数方法
function fn1(callback) {
  setTimeout(()=>{
    console.log('fn1')
    callback()
  }, 1000)
}

function fn2(callback) {
  setTimeout(()=>{
    console.log('fn2')
    callback()
  }, 1000)
}

function fn3() {
  setTimeout(()=>{
    console.log('fn3')
  }, 1000)
}



fn1(function(){
  fn2(function(){
    fn3()
  })
})
//Promise
function fn1() {
  return new Promise((resolve, reject)=>{
    setTimeout(()=>{
      console.log('fn1...')
      resolve()
    }, 1000)    
  })
}

function fn2() {
  return new Promise((resolve, reject)=>{
    setTimeout(()=>{
      console.log('fn2...')
      resolve()
    }, 1000)    
  })
}

function fn3() {
  return new Promise((resolve, reject)=>{
    setTimeout(()=>{
      console.log('fn3...')
      resolve()
    }, 1000)    
  })
}

function onerror() {
  console.log('error')
}

fn1().then(fn2).then(fn3).catch(onerror)

把如下 ajax 改造成一个返回 Promise对象的方法

改造前:jQuery 的 success / error 形式回调

function ajax(opts){
    var url = opts.url
    var type = opts.type || 'GET'
    var dataType = opts.dataType || 'json'
    var onsuccess = opts.onsuccess || function(){}
    var onerror = opts.onerror || function(){}
    var data = opts.data || {}

    var dataStr = []
    for(var key in data){
        dataStr.push(key + '=' + data[key])
    }
    dataStr = dataStr.join('&')

    if(type === 'GET'){
        url += '?' + dataStr
    }

    var xhr = new XMLHttpRequest()
    xhr.open(type, url, true)
    xhr.onload = function(){
        if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
            //成功了
            if(dataType === 'json'){
                onsuccess( JSON.parse(xhr.responseText))
            }else{
                onsuccess( xhr.responseText)
            }
        } else {
            onerror()
        }
    }
    xhr.onerror = onerror
    if(type === 'POST'){
        xhr.send(dataStr)
    }else{
        xhr.send()
    }
}

ajax({
    url: 'http://api.jirengu.com/weather.php',
    data: {
        city: '北京'
    },
    onsuccess: function(ret){
        console.log(ret)
    },
    onerror: function(){
        console.log('服务器异常')
    }
})

改造后:Promise回调

  function ajax(opts) {
        var url = opts.url
        var type = opts.type || 'GET'
        var dataType = opts.dataType || 'json'
        var data = opts.data || {}
        var dataStr = []

        for (var key in data) {
            dataStr.push(key + '=' + data[key])
        }

        dataStr = dataStr.join('&')

        if (type === 'GET') {
            url += '?' + dataStr
        }
        var promise = new Promise(function(resolve, reject){
            var xhr = new XMLHttpRequest()
            xhr.open(type, url, true)
            xhr.onload = function () {
                if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
                    //成功了
                    if (dataType === 'json') {
                        var ret = ( JSON.parse(xhr.responseText))
                        resolve(ret)
                    } else {
                        var ret = ( xhr.responseText)
                        resolve(ret)
                    }
                } else {
                    reject()
                }
            }
            if (type === 'POST') {
                xhr.send(dataStr)
            } else {
                xhr.send()
            }
        })
        return promise;
    }

    ajax({
        url: 'http://api.jirengu.com/weather.php',
        data: {
            city: '北京'
        }
    }).then(function(ret){
        console.log(ret)
    }).catch(function(){
        console.log('服务器异常')
    })

简化版

function ajax(){
    return new Promise((resolve, reject)=>{
        做事
        如果成功就调用 resolve
        如果失败就调用 reject
    })
}

var promise = ajax()
promise.then(successFn, errorFn)

在 Node.js中的应用

回调函数的第一个参数,必须是错误对象err(如果没有错误,该参数就是null);原因是执行分成两段,在这两段之间抛出的错误,程序无法捕捉,只能当作参数,传入第二段

fs.readFile(fileA, 'utf-8', function (err, data) {
  fs.readFile(fileB, 'utf-8', function (err, data) {
    if (err) throw err;
  console.log(data);
  });
});

var readFile = require('fs-readfile-promise');

readFile(fileA)
.then(function (data) {
  console.log(data.toString());
})
.then(function () {
  return readFile(fileB);
})
.then(function (data) {
  console.log(data.toString());
})
.catch(function (err) {
  console.log(err);
});

相关文章

  • 手写promise

    1. promise核心 使用 promise加入异步逻辑 前面的promise没有加异步的情况。增加异步就是在t...

  • 《JS原理、方法与实践》- ES6新增对象(下篇)

    异步处理(Promise) ES2015中新增的Promise对象专门用于处理异步。Promise对象使用then...

  • Node 学习(二)

    Promise学习 Promise含义 容器,保存异步操作的结果对象,获取异步操作的消息 Promise对象特点 ...

  • ES6 Primise异步编程

    异步操作流程化的手段 #Promise处理异步操作 Promise,使异步操作变得流程化的手段之一,例如“异步A ...

  • 循环多个 Promise 异步函数

    了解Promise 循环多个 Promise 异步函数

  • ES6 同步和异步、Promise

    一.同步与异步 1. Promise作用:解决异步回调的问题 二.Promise对象 目的:创建异步对象,当异步对...

  • react 中的 promise详解

    一、promise是什么?为什么会有promise? 首先,promise是js的抽象异步处理对象实现异步编程的方...

  • 简单记录一下Promise的使用方法

    Promise 作用 Promise意在让异步代码变得干净和直观,让异步代码变得井然有序。 Promise在设计上...

  • ES6-Promise

    构建Promise,异步实例 处理多个Promise实例 — Promise.all() 处理多个Promise实...

  • promise异步操作

    promise异步操作 定义:包含异步操作结果的对象 状态: 声明方式: new Promise((resolve...

网友评论

      本文标题:异步:Promise

      本文链接:https://www.haomeiwen.com/subject/hdpckqtx.html