我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Javascriptpromise异步编程浅析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Javascriptpromise异步编程浅析

promise 是什么

Promise 是异步编程的一种解决方案,可以替代传统的解决方案–回调函数和事件。ES6 统一了用法,并原生提供了 Promise 对象。作为对象,Promise 有以下两个特点:

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

(2)一旦状态改变了就不会再变,也就是说任何时候 Promise 都只有一种状态。

Promise 有三种状态,分别是 Pending (进行中)、Resolved (已完成)、Rejected (已失败)。Promise 从 Pending 状态开始,如果成功就转到成功态,并执行 resolve 回调函数;如果失败就转到失败状态并执行 reject 回调函数。

可以通过 Promise 的构造函数创建 Promise 对象

var promise = new Promise((resolve,reject) => {
  setTimeout(()=>{
    console.log("hello world")
}, 2000)
})

Promise 构造函数接受一个函数作为参数,该函数的两个参数是 resolve ,reject,它们由 JavaScript 引擎提供。其中 resolve 函数的作用是当 Promise 对象转移到成功,调用 resolve 并将操作结果作为其参数传递出去;reject 函数的作用是当 Promise 对象的状态变为失败时,将操作报出的错误作为参数传递出去。如下代码:

function greet(){
  var promise = new Promise(function(resolve,reject){
    var greet = "hello world"
    resolve(greet)
})
  return promise
}
greet().then(v=>{
  console.log(v)//*
})

Promise 的 then 方法,promise 的 then 方法带有一下三个参数:成功的回调,失败的回调,前进的回调。一般情况下只需要实现第一个,后面的是可选的。Promise 中最为重要的状态,通过 then 的状态传递可以实现的回调函数链式操作的实现。先执行以下代码:

function greet () {
  var promise = new Promise (function(resolve, reject){
    var greet = "hello world"
    resolve(greet)
  })
  return promise
}
var p = greet().then(v => {
  console.log(v)  // Promise { <pending> }
})
console.log(p)  // hello world

catch 用法

function judgeNumber(num){
    var promise1 = new Promise(function(resolve,reject){
        num =5;
        if(num<5){
            resolve("num小于5,值为:"+num);
        }else{
            reject("num不小于5,值为:"+num);
        }
    });
    return promise1;
}
judgeNumber().then(
    function(message){
        console.log(message);
    }
)
.catch(function(message){
    console.log(message);
})

Promise 的 all 方法提供了并行执行异步操作的能力,在 all 中所有异步操作结束后才执行回调。

function p1(){
    var promise1 = new Promise(function(resolve,reject){
        console.log("p1的第一条输出语句");
        console.log("p1的第二条输出语句");
        resolve("p1完成");
    })
    return promise1;
}
function p2(){
    var promise2 = new Promise(function(resolve,reject){
        console.log("p2的第一条输出语句");
        setTimeout(()=>{console.log("p2的第二条输出语句");resolve("p2完成")},2000);
    })
    return promise2;
}
function p3(){
    var promise3 = new Promise(function(resolve,reject){
        console.log("p3的第一条输出语句");
        console.log("p3的第二条输出语句");
        resolve("p3完成")
    });
    return  promise3;
}
Promise.all([p1(),p2(),p3()]).then(function(data){
    console.log(data);
})
p1的第一条输出语句
p1的第二条输出语句
p2的第一条输出语句
p3的第一条输出语句
p3的第二条输出语句
p2的第二条输出语句
['p1完成', 'p2完成', 'p3完成']

在 all 中的回调函数中,等到所有的 Promise 都执行完,再来执行回调函数,race 则不同它等到第一个 Promise 改变状态就开始执行回调函数。将上面的all改为race,得到

Promise.race([p1(),p2(),p3()]).then(function(data){
    console.log(data);
})

如何实现一个 promise

(function(window,undefined){
// resolve 和 reject 最终都会调用该函数
var final = function(status,value){
    var promise = this, fn, st;
    if(promise._status !== 'PENDING') return;
    // 所以的执行都是异步调用,保证then是先执行的
    setTimeout(function(){
        promise._status = status;
        st = promise._status === 'FULFILLED'
        queue = promise[st ? '_resolves' : '_rejects'];
        while(fn = queue.shift()) {
            value = fn.call(promise, value) || value;
        }
        promise[st ? '_value' : '_reason'] = value;
        promise['_resolves'] = promise['_rejects'] = undefined;
    });
}
//参数是一个函数,内部提供两个函数作为该函数的参数,分别是resolve 和 reject
var Promise = function(resolver){
    if (!(typeof resolver === 'function' ))
        throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
    //如果不是promise实例,就new一个
    if(!(this instanceof Promise)) return new Promise(resolver);
    var promise = this;
    promise._value;
    promise._reason;
    promise._status = 'PENDING';
    //存储状态
    promise._resolves = [];
    promise._rejects = [];
    //
    var resolve = function(value) {
        //由於apply參數是數組
        final.apply(promise,['FULFILLED'].concat([value]));
    }
    var reject = function(reason){
        final.apply(promise,['REJECTED'].concat([reason]));
    }
    resolver(resolve,reject);
}
Promise.prototype.then = function(onFulfilled,onRejected){
    var promise = this;
    // 每次返回一个promise,保证是可thenable的
    return new Promise(function(resolve,reject){
        function handle(value) {
            // 這一步很關鍵,只有這樣才可以將值傳遞給下一個resolve
            var ret = typeof onFulfilled === 'function' && onFulfilled(value) || value;
            //判断是不是promise 对象
            if (ret && typeof ret ['then'] == 'function') {
                ret.then(function(value) {
                    resolve(value);
                }, function(reason) {
                    reject(reason);
                });
            } else {
                resolve(ret);
            }
        }
        function errback(reason){
            reason = typeof onRejected === 'function' && onRejected(reason) || reason;
            reject(reason);
        }
        if(promise._status === 'PENDING'){
            promise._resolves.push(handle);
            promise._rejects.push(errback);
        }else if(promise._status === FULFILLED){ // 状态改变后的then操作,立刻执行
            callback(promise._value);
        }else if(promise._status === REJECTED){
            errback(promise._reason);
        }
    });
}
Promise.prototype.catch = function(onRejected){
    return this.then(undefined, onRejected)
}
Promise.prototype.delay = function(ms,value){
    return this.then(function(ori){
        return Promise.delay(ms,value || ori);
    })
}
Promise.delay = function(ms,value){
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            resolve(value);
            console.log('1');
        },ms);
    })
}
Promise.resolve = function(arg){
    return new Promise(function(resolve,reject){
        resolve(arg)
    })
}
Promise.reject = function(arg){
    return Promise(function(resolve,reject){
        reject(arg)
    })
}
Promise.all = function(promises){
    if (!Array.isArray(promises)) {
        throw new TypeError('You must pass an array to all.');
    }
    return Promise(function(resolve,reject){
        var i = 0,
            result = [],
            len = promises.length,
            count = len
        //这里与race中的函数相比,多了一层嵌套,要传入index
        function resolver(index) {
          return function(value) {
            resolveAll(index, value);
          };
        }
        function rejecter(reason){
            reject(reason);
        }
        function resolveAll(index,value){
            result[index] = value;
            if( --count == 0){
                resolve(result)
            }
        }
        for (; i < len; i++) {
            promises[i].then(resolver(i),rejecter);
        }
    });
}
Promise.race = function(promises){
    if (!Array.isArray(promises)) {
        throw new TypeError('You must pass an array to race.');
    }
    return Promise(function(resolve,reject){
        var i = 0,
            len = promises.length;
        function resolver(value) {
            resolve(value);
        }
        function rejecter(reason){
            reject(reason);
        }
        for (; i < len; i++) {
            promises[i].then(resolver,rejecter);
        }
    });
}
window.Promise = Promise;
})(window);

async await

async 表示这是一个 async 函数, await 只能用在 async 函数里面,不能单独使用

async 返回的是一个 Promise 对象,await 就是等待这个 promise 的返回结果后,再继续执行

await 等待的是一个 Promise 对象,后面必须跟一个 Promise 对象,但是不必写 then(),直接就可以得到返回值

async/await 的优点

方便级联调用:即调用依次发生的场景;

同步代码编写方式:Promise 使用 then 函数进行链式调用,一直点点点,是一种从左向右的横向写法;async/await 从上到下,顺序执行,就像写同步代码一样,更符合代码编写习惯;

多个参数传递:Promise 的 then 函数只能传递一个参数,虽然可以通过包装成对象来传递多个参数,但是会导致传递冗余信息,频繁的解析又重新组合参数,比较麻烦;async/await 没有这个限制,可以当做普通的局部变量来处理,用 let 或者 const 定义的块级变量想怎么用就怎么用,想定义几个就定义几个,完全没有限制,也没有冗余工作;

同步代码和异步代码可以一起编写:使用 Promise 的时候最好将同步代码和异步代码放在不同的 then 节点中,这样结构更加清晰;async/await 整个书写习惯都是同步的,不需要纠结同步和异步的区别,当然,异步过程需要包装成一个 Promise 对象放在 await 关键字后面;

基于协程:Promise 是根据函数式编程的范式,对异步过程进行了一层封装,async/await 基于协程的机制,是真正的“保存上下文,控制权切换……控制权恢复,取回上下文”这种机制,是对异步过程更精确的一种描述;

async/await 是对 Promise 的优化:async/await 是基于 Promise 的,是进一步的一种优化,不过在写代码时,Promise 本身的 API 出现得很少,很接近同步代码的写法

到此这篇关于Javascript promise异步编程浅析的文章就介绍到这了,更多相关Js promise异步内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Javascriptpromise异步编程浅析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Javascriptpromise异步编程浅析

这篇文章主要介绍了Javascriptpromise异步编程,Promise是异步编程的一种解决方案,可以替代传统的解决方案–回调函数和事件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
2023-05-17

浅谈node.js中async异步编程

1.什么是异步编程?异步编程是指由于异步I/O等因素,无法同步获得执行结果时, 在回调函数中进行下一步操作的代码编写风格,常见的如setTimeout函数、ajax请求等等。 示例:for (var i = 1; i <= 3; i++)
2022-06-04

浅谈 PHP 函数的异步编程

在 php 中,异步编程允许在不阻塞执行流的情况下执行耗时任务。实现异步编程的技术包括:回调函数:函数指针,在另一个函数执行完成后执行代码。协程:轻量级多任务机制,允许在同一线程中切换多个函数执行。并行化:使用不同的线程或进程同时执行多个任
浅谈 PHP 函数的异步编程
2024-05-05

浅谈Node异步编程的机制

本文介绍了Node异步编程,分享给大家,具体如下: 目前的异步编程主要解决方案有:事件发布/订阅模式Promise/Deferred模式流程控制库事件发布/订阅模式 Node自身提供了events模块,可以轻松实现事件的发布/订阅//订阅
2022-06-04

C#异步编程的示例分析

小编给大家分享一下C#异步编程的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!异步编程在处理并发方面被使用的越来越多,之所以说上面一句话,是为了区分多线程
2023-06-17

浅析JS的异步函数async/await

本篇文章带大家了解一下JavaScript的异步函数 async/await,希望对大家有所帮助!
2023-05-14

JavaScript中异步编程的示例分析

这篇文章给大家分享的是有关JavaScript中异步编程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。目的提升开发效率,编写易维护的代码引子问题请求时候为什么页面卡死??$.ajax({ url: "
2023-06-15

c#中异步编程的示例分析

这篇文章给大家分享的是有关c#中异步编程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、什么算异步?  广义来讲,两个工作流能同时进行就算异步,例如,CPU与外设之间的工作流就是异步的。在面向服务的系
2023-06-14

Node.js异步编程实例代码分析

这篇文章主要介绍了Node.js异步编程实例代码分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Node.js异步编程实例代码分析文章都会有所收获,下面我们一起来看看吧。异步编程案例一function int
2023-07-04

python中asyncio异步编程的示例分析

这篇文章将为大家详细讲解有关python中asyncio异步编程的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1. 想学asyncio,得先了解协程携程的意义:计算型的操作,利用协程来回切换
2023-06-14

JS异步编程Promise对象实例分析

这篇文章主要介绍“JS异步编程Promise对象实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“JS异步编程Promise对象实例分析”文章能帮助大家解决问题。1、单线程模型单线程模型指的是,
2023-07-02

编程热搜

目录