JS基础(五)

// 1. JS是单线程 解决方式 异步

// 2. 异步的解决方式 事件轮循

// 3. 事件轮循的核心-回调函数

// let arr = [1,34,3]

// let arr2 =  arr.sort()

// setTimeout(() => alert(arr2),6000)

// //同步回调函数 异步回调函数

// console.log(arr)

// 回调

// promise

// 异步编程的一种解决方案,比传统的解决方案-回调函数和事件-更合理

// 三种状态

// pending【待定】初始状态

// fulfilled [实现] 操作成功

// rejected 【拒绝】 操作失败

// Promise 是将“生产者代码”和“消费者代码”连接在一起的一个特殊的 JavaScript 对象。用我们的类比来说:这就是就像是“订阅列表”。“生产者代码”花费它所需的任意长度时间来产出所承诺的结果,而 “promise” 将在它(译注:指的是“生产者代码”,也就是下文所说的 executor)准备好时,将结果向所有订阅了的代码开放。

// 这种类比并不十分准确,因为 JavaScipt 的 promise 比简单的订阅列表更加复杂:它们还拥有其他的功能和局限性。但以此开始挺好的。

// Promise 对象的构造器(constructor)语法如下:

// let promise = new promise(传一个函数)

// let xx = Promise(function (resolve, reject) {

//    resolve(console.log('xxxxx'))

// });

//

// xx.then(function (res)) {

//    console.log("yyyy")

// }

// 传递给 new Promise 的函数被称为 executor。当 new Promise 被创建,executor 会自动运行。它包含最终应产出结果的生产者代码。按照上面的类比:executor 就是“歌手”。

// 它的参数 resolve 和 reject 是由 JavaScript 自身提供的回调。我们的代码仅在 executor 的内部。

// 当 executor 获得了结果,无论是早还是晚都没关系,它应该调用以下回调之一:

// resolve(value) —— 如果任务成功完成并带有结果 value。

// reject(error) —— 如果出现了 error,error 即为 error 对象。

// 所以总结一下就是:executor 会自动运行并尝试执行一项工作。尝试结束后,如果成功则调用 resolve,如果出现 error 则调用 reject。

// 由 new Promise 构造器返回的 promise 对象具有以下内部属性:

// state —— 最初是 "pending",然后在 resolve 被调用时变为 "fulfilled",或者在 reject 被调用时变为 "rejected"。

// result —— 最初是 undefined,然后在 resolve(value) 被调用时变为 value,或者在 reject(error) 被调用时变为 error。

// let promise = new Promise(function (resolve,reject){

//    console.log("no")

//    // 当 promise 被构造完成时,自动执行此函数

//    // 1 秒后发出工作已经被完成的信号,并带有结果 "done"

//    setTimeout(() => resolve(console.log("yes")),1000)

//    console.log("done")

// });

// executor 被自动且立即调用(通过 new Promise)。

// executor 接受两个参数:resolve 和 reject。这些函数由 JavaScipt 引擎预先定义,因此我们不需要创建它们。我们只需要在准备好(译注:指的是 executor 准备好)时调用其中之一即可。

// // 经过 1 秒的“处理”后,executor 调用 resolve("done") 来产生结果。这将改变 promise 对象的状态:

// let promise1 = new Promise(function (resolve, reject) {

//    // 1 秒后发出工作已经被完成的信号,并带有 error

//    setTimeout(() => reject(new Error("Whoops")),1000)

// });

// 对 reject(...) 的调用将 promise 对象的状态移至 "rejected":

// 总而言之,executor 应该执行一项工作(通常是需要花费一些时间的事儿),然后调用 resolve 或 reject 来改变对应的 promise 对象的状态。

// 与最初的 “pending” promise 相反,一个 resolved 或 rejected 的 promise 都会被称为 “settled”。

// 这儿只能有一个结果或一个 error

// executor 只能调用一个 resolve 或一个 reject。任何状态的更改都是最终的。

// 所有其他的再对 resolve 和 reject 的调用都会被忽略:

// 这儿的宗旨是,一个被 executor 完成的工作只能有一个结果或一个 error。

// 并且,resolve/reject 只需要一个参数(或不包含任何参数),并且将忽略额外的参数。

// let promise = new Promise(function(resolve, reject) {

//    resolve("done");

//    reject(new Error("…")); // 被忽略

//    setTimeout(() => resolve("…")); // 被忽略

// });

// 以 Error 对象 reject

// // 如果什么东西出了问题, executor 应该调用 reject。这可以使用任何类型的参数来完成(就像 resolve 一样)。但是建议使用 Error 对象(或继承自 Error 的对象)。这样做的理由很快就会显而易见。

// Resolve/reject 可以立即进行,实际上,executor 通常是异步执行某些操作,并在一段时间后调用 resolve/reject,但这不是必须的。我们还可以立即调用 resolve 或 reject,就像这样:

// let promise = new Promise(function (resolve, reject) {

//    resolve(123)

// })

// 例如,当我们开始做一个任务时,但随后看到一切都已经完成并已被缓存时,可能就会发生这种情况。

// 这挺好。我们立即就有了一个 resolved 的 promise。

// state 和 result 都是内部的

// Promise 对象的 state 和 result 属性都是内部的。我们无法直接访问它们。但我们可以对它们使用 .then/.catch/.finally 方法。我们在下面对这些方法进行了描述。

// 消费者:then,catch,finally

// Promise 对象充当的是 executor(“生产者代码”或“歌手”)和消费函数(“粉丝”)之间的连接,后者将接收结果或 error。可以通过使用 .then、.catch 和 .finally 方法为消费函数进行注册。

// let promise = new Promise(function (resolve, reject) {

//    alert('saaa')

//    setTimeout(() => resolve("done"),3000)

// });

// promise.then(

//    function (resault){

//        alert('xxxx')

//    }

// )

// .then 的第一个参数是一个函数,该函数将在 promise resolved 后运行并接收结果。

// .then 的第二个参数也是一个函数,该函数将在 promise rejected 后运行并接收 error。

// 在 reject 的情况下,运行第二个:

// let promise = new Promise(function (resolve, reject) {

//    setTimeout((() => reject(new Error('xxxx'))),2000)

// })

// promise.then(

//    result = alert(result)

//    error = alert(error)

// )

// let promise = new Promise(function (resolve, reject) {

//    setTimeout(() => resolve('done'),1000)

// })

// promise.then(alert)

// catch

// 如果我们只对 error 感兴趣,那么我们可以使用 null 作为第一个参数:.then(null, errorHandlingFunction)。或者我们也可以使用 .catch(errorHandlingFunction),其实是一样的:

// let promise = Promise(function (resolve, reject) {

//    setTimeout(() => reject(new Error("xxxx")),2000)

// })

// promise.catch(alert)

// 如果我们只对 error 感兴趣,那么我们可以使用 null 作为第一个参数:.then(null, errorHandlingFunction)。或者我们也可以使用 .catch(errorHandlingFunction),其实是一样的:

// catch(f) 调用是 .then(null, f) 的完全的模拟,它只是一个简写形式。

// finally

// new Promise((resolve, reject) => {

//    /* 做一些需要时间的事儿,然后调用 resolve/reject */

// })

//    // 在 promise 为 settled 时运行,无论成功与否

//    .finally(() => stop loading indicator)

// // 所以,加载指示器(loading indicator)始终会在我们处理结果/错误之前停止

// .then(result => show result, err => show error)

// new Promise((resolve, reject) => {

//

// })

//    .finally(() => stop)

//    .then(result => showResault, error => showError)

// finally 处理程序(handler)没有参数。在 finally 中,我们不知道 promise 是否成功。没关系,因为我们的任务通常是执行“常规”的定稿程序(finalizing procedures)。

// finally 处理程序将结果和 error 传递给下一个处理程序。

// 例如,在这儿结果被从 finally 传递给了 then:

// new Promise((resolve, reject) => {

//    setTimeout(() => resolve("result"), 2000)

// })

//    .finally(() => alert("Promise ready"))

//    .then(result => alert(result)); // <-- .then 对结果进行处理

// new Promise((resolve, reject) => {

//    throw new Error("error");

// })

//    .finally(() => alert("Promise ready"))

//    .catch(err => alert(err));  // <-- .catch 对 error 对象进行处理

// 这非常方便,因为 finally 并不是意味着要处理 promise 的结果。所以它将结果传递了下去。

// 如果 promise 为 pending 状态,.then/catch/finally 处理程序(handler)将等待它。否则,如果 promise 已经是 settled 状态,它们就会运行:

// 下面这 promise 在被创建后立即变为 resolved 状态

// let promise = new Promise(resolve => resolve("done!"));

// promise.then(alert); // done!(现在显示)

// 请注意这使得 promise 比现实生活中的“订阅列表”方案强大得多。如果歌手已经发布了他们的单曲,然后某个人在订阅列表上进行了注册,则他们很可能不会收到该单曲。实际生活中的订阅必须在活动开始之前进行。

// Promise 则更加灵活。我们可以随时添加处理程序(handler):如果结果已经在了,它们就会执行。

// function loadScript(src, callback) {

//    let script = document.createElement('script')

//    script.src = src

//    script.onload = () => callback(null, script)

//    script.onerror = () => callback(new Error(`error ${src}`))

//    document.head.append(script)

// }

// 改写

function loadScript(scr) {

return new Promise(function (resolve, reject) {

let script =document.createElement('script')

script.src = src

script.onload = () => resolve(script)

script.onerror = () => reject(new Error(`error ${src}`))

document.head.append(script)

})

}

// 用法

let promise =loadScript("xxxxx")

promise.then(

script =>alert(`${script.src} is loaded!`),

    error =>alert(`Error: ${error.message}`)

)

// promise.then(script => alert('Another handler...'));

// Promises    Callbacks

// Promises 允许我们按照自然顺序进行编码。首先,我们运行 loadScript 和 .then 来处理结果。  在调用 loadScript(script, callback) 时,在我们处理的地方(disposal)必须有一个 callback 函数。换句话说,在调用 loadScript 之前,我们必须知道如何处理结果。

function delay(ms) {

return new Promise(resolve =>setTimeout(resolve, ms));

}

delay(3000).then(() =>alert('runs after 3 seconds'));

// Promise 链

new Promise(function(resolve, reject) {

setTimeout(() => resolve(1), 1000); // (*)

}).then(function(result) {// (**)

    alert(result); // 1

    return result *2;

}).then(function(result) {// (***)

    alert(result); // 2

    return result *2;

}).then(function(result) {

alert(result); // 4

    return result *2;

});

// 它的理念是将 result 通过 .then 处理程序(handler)链进行传递。

// 运行流程如下:

// 初始 promise 在 1 秒后进行 resolve (*),

// 然后 .then 处理程序(handler)被调用 (**)。

// 它返回的值被传入下一个 .then 处理程序(handler)(***)

// ……依此类推。

// 随着 result 在处理程序(handler)链中传递,我们可以看到一系列的 alert 调用:1 → 2 → 4。

// 之所以这么运行,是因为对 promise.then 的调用会返回了一个 promise,所以我们可以在其之上调用下一个 .then。

// 当处理程序(handler)返回一个值时,它将成为该 promise 的 result,所以将使用它调用下一个 .then。

// 新手常犯的一个经典错误:从技术上讲,我们也可以将多个 .then 添加到一个 promise 上。但这并不是 promise 链(chaining)。

// 我们在这里所做的只是一个 promise 的几个处理程序(handler)。它们不会相互传递 result;相反,它们之间彼此独立运行处理任务。

// 这里它的一张示意图(你可以将其与上面的链式调用做一下比较):

// 在同一个 promise 上的所有 .then 获得的结果都相同 — 该 promise 的结果。所以,在上面的代码中,所有 alert 都显示相同的内容:1。

// 实际上我们极少遇到一个 promise 需要多处理程序(handler)的情况。使用链式调用的频率更高。

// let promise = new Promise(function(resolve, reject) {

//    setTimeout(() => resolve(1), 1000);

// });

// promise.then(function(result) {

//    alert(result); // 1

//    return result * 2;

// });

// promise.then(function(result) {

//    alert(result); // 1

//    return result * 2;

// });

// promise.then(function(result) {

//    alert(result); // 1

//    return result * 2;

// });

// .then(handler) 中所使用的处理程序(handler)可以创建并返回一个 promise。

// 在这种情况下,其他的处理程序(handler)将等待它 settled 后再获得其结果(result)。

new Promise(function(resolve, reject) {

setTimeout(() => resolve(1), 1000);

}).then(function(result) {

alert(result); // 1

    return new Promise((resolve, reject) => {// (*)

        setTimeout(() => resolve(result *2), 1000);

    });

}).then(function(result) {// (**)

    alert(result); // 2

    return new Promise((resolve, reject) => {

setTimeout(() => resolve(result *2), 1000);

    });

}).then(function(result) {

alert(result); // 4

});

// 这里第一个 .then 显示 1 并在 (*) 行返回 new Promise(…)。1 秒后它会进行 resolve,然后 result(resolve 的参数,在这里它是 result*2)被传递给第二个 .then 的处理程序(handler)。这个处理程序(handler)位于 (**) 行,它显示 2,并执行相同的动作(action)。

Promise.all()// 所有结果成功

Promise.race()//只要有一个返回不管成功或者失败

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容