欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

Promise 廖雪峰的官方网站 有大用 有大大用 有大大大用

最后更新: 2017/11/15 22:53 / 阅读: 181580313

在JavaScript的世界中,所有代码都是单线程执行的。

由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。异步执行可以用回调函数实现:

function callback() {
    console.log('Done');
}
console.log('before setTimeout()');
setTimeout(callback, 1000); // 1秒钟后调用callback函数
console.log('after setTimeout()');

观察上述代码执行,在Chrome的控制台输出可以看到:

before setTimeout()
after setTimeout()
(等待1秒后)
Done

可见,异步操作会在将来的某个时间点触发一个函数调用。

AJAX就是典型的异步操作。以上一节的代码为例:

request.onreadystatechange = function () {
    if (request.readyState === 4) {
        if (request.status === 200) {
            return success(request.responseText);
        } else {
            return fail(request.status);
        }
    }
}

把回调函数success(request.responseText)fail(request.status)写到一个AJAX操作里很正常,但是不好看,而且不利于代码复用。

有没有更好的写法?比如写成这样:

var ajax = ajaxGet('http://...');
ajax.ifSuccess(success)
    .ifFail(fail);

这种链式写法的好处在于,先统一执行AJAX逻辑,不关心如何处理结果,然后,根据结果是成功还是失败,在将来的某个时候调用success函数或fail函数。

古人云:“君子一诺千金”,这种“承诺将来会执行”的对象在JavaScript中称为Promise对象。

Promise有各种开源实现,在ES6中被统一规范,由浏览器直接支持。先测试一下你的浏览器是否支持Promise:

'use strict';

new Promise(function () {});
支持Promise!

我们先看一个最简单的Promise例子:生成一个0-2之间的随机数,如果小于1,则等待一段时间后返回成功,否则返回失败:

function test(resolve, reject) {
    var timeOut = Math.random() * 2;
    log('set timeout to: ' + timeOut + ' seconds.');
    setTimeout(function () {
        if (timeOut < 1) {
            log('call resolve()...');
            resolve('200 OK');
        }
        else {
            log('call reject()...');
            reject('timeout in ' + timeOut + ' seconds.');
        }
    }, timeOut * 1000);
}

这个test()函数有两个参数,这两个参数都是函数,如果执行成功,我们将调用resolve('200 OK'),如果执行失败,我们将调用reject('timeout in ' + timeOut + ' seconds.')。可以看出,test()函数只关心自身的逻辑,并不关心具体的resolvereject将如何处理结果。

有了执行函数,我们就可以用一个Promise对象来执行它,并在将来某个时刻获得成功或失败的结果:

var p1 = new Promise(test);
var p2 = p1.then(function (result) {
    console.log('成功:' + result);
});
var p3 = p2.catch(function (reason) {
    console.log('失败:' + reason);
});

变量p1是一个Promise对象,它负责执行test函数。由于test函数在内部是异步执行的,当test函数执行成功时,我们告诉Promise对象:

// 如果成功,执行这个函数:
p1.then(function (result) {
    console.log('成功:' + result);
});

test函数执行失败时,我们告诉Promise对象:

p2.catch(function (reason) {
    console.log('失败:' + reason);
});

Promise对象可以串联起来,所以上述代码可以简化为:

new Promise(test).then(function (result) {
    console.log('成功:' + result);
}).catch(function (reason) {
    console.log('失败:' + reason);
});

实际测试一下,看看Promise是如何异步执行的:

'use strict';

// 清除log:
var logging = document.getElementById('test-promise-log');
while (logging.children.length > 1) {
    logging.removeChild(logging.children[logging.children.length - 1]);
}

// 输出log到页面:
function log(s) {
    var p = document.createElement('p');
    p.innerHTML = s;
    logging.appendChild(p);
}
(no output)

Log:

start new Promise...

set timeout to: 0.04930280052661917 seconds.

call resolve()...

Done: 200 OK

可见Promise最大的好处是在异步执行的流程中,把执行代码和处理结果的代码清晰地分离了:

promise

Promise还可以做更多的事情,比如,有若干个异步任务,需要先做任务1,如果成功后再做任务2,任何任务失败则不再继续并执行错误处理函数。

要串行执行这样的异步任务,不用Promise需要写一层一层的嵌套代码。有了Promise,我们只需要简单地写:

job1.then(job2).then(job3).catch(handleError);

其中,job1job2job3都是Promise对象。

下面的例子演示了如何串行执行一系列需要异步计算获得结果的任务:

'use strict';

var logging = document.getElementById('test-promise2-log');
while (logging.children.length > 1) {
    logging.removeChild(logging.children[logging.children.length - 1]);
}

function log(s) {
    var p = document.createElement('p');
    p.innerHTML = s;
    logging.appendChild(p);
}
(no output)

Log:

start new Promise...

calculating 123 x 123...

calculating 15129 + 15129...

calculating 30258 x 30258...

calculating 915546564 + 915546564...

Got value: 1831093128

setTimeout可以看成一个模拟网络等异步执行的函数。现在,我们把上一节的AJAX异步执行函数转换为Promise对象,看看用Promise如何简化异步处理:

'use strict';

// ajax函数将返回Promise对象:
function ajax(method, url, data) {
    var request = new XMLHttpRequest();
    return new Promise(function (resolve, reject) {
        request.onreadystatechange = function () {
            if (request.readyState === 4) {
                if (request.status === 200) {
                    resolve(request.responseText);
                } else {
                    reject(request.status);
                }
            }
        };
        request.open(method, url);
        request.send(data);
    });
}
Result:

除了串行执行若干异步任务外,Promise还可以并行执行异步任务。

试想一个页面聊天系统,我们需要从两个不同的URL分别获得用户的个人信息和好友列表,这两个任务是可以并行执行的,用Promise.all()实现如下:

var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, 'P1');
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, 'P2');
});
// 同时执行p1和p2,并在它们都完成后执行then:
Promise.all([p1, p2]).then(function (results) {
    console.log(results); // 获得一个Array: ['P1', 'P2']
});

有些时候,多个异步任务是为了容错。比如,同时向两个URL读取用户的个人信息,只需要获得先返回的结果即可。这种情况下,用Promise.race()实现:

var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, 'P1');
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, 'P2');
});
Promise.race([p1, p2]).then(function (result) {
    console.log(result); // 'P1'
});

由于p1执行较快,Promise的then()将获得结果'P1'p2仍在继续执行,但执行结果将被丢弃。

如果我们组合使用Promise,就可以把很多异步任务以并行和串行的方式组合起来执行。

读后有收获可以支付宝请作者喝咖啡:

还可以分享给朋友:

 分享到微博



评论

  • Promise里resolve(arg)里的参数arg是Promise对象的情况

    蓝田暖玉 created at May 11, 2022 5:17 PM, Last updated at May 13, 2022 1:50 PM

    按我的理解,resolve会把其参数交给then中的函数,作为回调的参数,但我发现这样一份代码,其中将第一个Promise对象传给了第二个Promise中的resolve,而回调函数是打印。但事实上,打印的不是Promise对象,最终打印的是第一个对象中resolve的参数。但then方法的调用者确确实实是第二个对象。注意这不是链式调用中return一个Promise的写法,而是Promise是参数。谁能解释一下这种情况下then为什么能获得非调用对象传过来的参数。

    const setDelay = (millisecond) => {
      return new Promise((resolve, reject)=>{
          if (typeof millisecond != 'number') reject(new Error('参数必须是number类型'));
          setTimeout(()=> {
            resolve(`我延迟了${millisecond}毫秒后输出的`)
          }, millisecond)
      })
    } // 第一个promise对象
    const setDelaySecond = (seconds) => {
      return new Promise((resolve, reject)=>{
          if (typeof seconds != 'number' || seconds > 10) reject(new Error('参数必须是number类型,并且小于等于10'));
          setTimeout(()=> {
            console.log(`先是setDelaySeconds函数输出,延迟了${seconds}秒,一共需要延迟${seconds+2}秒`)
            resolve(setDelay(2000)) // 这里依赖上一个Promise
          }, seconds * 1000)
      })
    } // 第二个promise对象
    setDelaySecond(3).then((result)=>{
      console.log(result)  
    }).catch((err)=>{
      console.log(err);
    })
    

     Read More

    • Created at May 13, 2022 10:39 AM

      如果 then 中的回调函数返回一个未定状态(pending)的 Promise,那么 then 返回 Promise 的状态也是未定的,并且它的终态与那个 Promise 的终态相同;同时,它变为终态时调用的回调函数参数与那个 Promise 变为终态时的回调函数的参数是相同的。 

      MDN上这句应该可以解释你这个问题吧

    • Created at May 13, 2022 1:50 PM

      then中的回调函数就是个打印语句,没有返回值

  • then串联里setTimeout不同方式导致的不同结果???

    ya_ma_dei created at June 23, 2021 6:19 PM, Last updated at February 26, 2022 9:11 PM

    function log(txt)

    {

        console.log(txt);

    }

    function multiply(input) {

        return new Promise(function (resolve, reject) {

            log('calculating ' + input + ' x ' + input + '...');

            // setTimeout(resolve, 500, input*input);

            setTimeout(resolve(input*input), 500);

        });

    }

    function add(input) {

        return new Promise(function (resolve, reject) {

            log('calculating ' + input + ' + ' + input + '...');

            // setTimeout(resolve, 500, input+input);

            setTimeout(resolve(input+input), 500);

        });

    }

    var p = new Promise(function (resolve, reject) {

        log('start new Promise...');

        resolve(123);

    });

    p.then(multiply)

     .then(add)

     .then(multiply)

     .then(add)

     .then(function (result) {

        log('Got value: ' + result);

    });

    结果直接就全部打印出来了,没有延时。

    查了setTimeout的用法,第三个参数就是传给第一个参数(函数)的参数,应该和resolve(input*input)一样啊,那为什么写成resolve(input*input)就没有延时效果了呢?

     Read More

    • Created at February 26, 2022 9:11 PM

      setTimeout 的第一个参数是回调函数的入口(地址),也就是resolve,不是可执行语句resolve(input*input),resolve一旦执行,会直接将内容传递给Promise对象的PromiseResult,写成可执行语句,setTimeout可能会获得一个未定义或未知的函数入口,具体可以调试看看。

  • Promise 对象

    Junes_99994 created at February 26, 2022 8:12 PM, Last updated at February 26, 2022 8:15 PM

    浏览器前端显示进程(render process)里有很多线程,其中执行js代码的是主线程(main thread,MT)

    通过异步(async)方法,可以将当前任务交给其他线程(或进程)如网络线程(network thread,NT)并行处理。

    // promiselet url = "https://get.geojs.io/v1/ip/country.json?ip=223.5.5.5fetch(url)    .then(        response => {            console.log(response.status);            let json = response.json()            console.log(json);// Promise object            return json;        },        err => {            return new Promise((resolve, reject) => reject(err.message));        }    )    .then(        data => {            console.log(data)        },        err => console.log("hi:", err.message || err)    )    // .catch(err => console.error('Error:', err))
    

    如上过程很简单

    Promise 是一个语法糖,它可以将一个异步操作结束时的状态(成败)、对应的数据打包,再通过promise.then,将对应的处理函数也捆绑上去。

    Promise 方法以一个函数f为参数,当创建一个Promise对象 p 后,p 调用 f(resolve, reject),resolve和reject这两个函数会将其在函数 f 中接受到的内容专递给Promise对象的PromiseResult属性,并更新PromiseState——如果调用的是resolve则为'fulfilled',反之为'rejected' 。如果谁都没有调用,则为'pending'等待中。如果在f中多次重复调用这两函数,则最先调用的函数有效,之后的无效。

    p.then 会根据

     Read More

    • Created at February 26, 2022 8:15 PM

      p.then 会根据 p 的PromiseResult选择调用回调函数,并将之前调用f获得的内容专递给相应回调函数。

      // promise
      let url = "https://get.geojs.io/v1/ip/country.json?ip=223.5.5.5"
      fetch(url)
          .then(
              response => {
                  console.log(response.status);
                  let json = response.json()
                  console.log(json);// Promise object
                  return json;
              },
              err => {
                  return new Promise((resolve, reject) => reject(err.message));
              }
          )
          .then(
              data => {
                  console.log(data)
              },
              err => console.log("hi:", err.message || err)
          )
          // .catch(err => console.error('Error:', err))
      

       Read More

  1. MT 请求查询ip=223.5.5.5归属地

  2. NT 尝试获取,得到两种可能结果:完成 或 失败(如拔网线,缺省部分链接资源地址)

  3. MT将fetch的结果包装到Promise对象p1中,选择执行其后then中的两个函数,并再次将结果包装到p2中

  4. MT调用p2的then方法,显示状态内容

  • catch和then互换位置

    寻一个答案an created at April 7, 2018 5:04 PM, Last updated at April 21, 2021 2:33 PM

    //在这个例子里我把catcht和then调换了位置, 执行之后发现有问题 new Promise(function (resolve, reject) { log('start new Promise...'); var timeOut = Math.random() 2; log('set timeout to: ' + timeOut + ' seconds.'); setTimeout(function () { if (timeOut < 1) { log('call resolve()...'); resolve('200 OK'); } else { log('call reject()...'); reject('timeout in ' + timeOut + ' seconds.'); } }, timeOut 1000); }).catch(function (r) { log('Done: ' + r); }).then(function (reason) { log('Failed: ' + reason); });

    这是输出小于1的情况, 没问题: start new Promise...

    set timeout to: 0.6963593041800307 seconds.

    call resolve()...

    Failed: 200 OK

    这是输出大于1的情况, 多输出一个Failed: undefined: start new Promise...

    set timeout to: 1.4453681319996927 seconds.

    call reject()...

    Done: timeout in 1.4453681319996927 seconds.

    Failed: undefined

     Read More

    • Created at October 5, 2018 4:28 AM

      是then(function(){}).catch(function(){})换位置肯定错啊

    • Created at November 3, 2018 3:13 PM

      Promise 不论成功或失败都会调用 then 然而catch() 只有当 promise 失败时才会调用

      所以当失败的时候既执行了then又执行了catch,只不过reject只会将参数传递给catch方法,并不传递then方法所以顺序写反失败后then就输出了undefined,而catch是正常输出结果

    • Created at March 18, 2019 9:57 PM

      虽然知道原因,但我觉得我讲起来你们可能听不懂,因为要阅读文档,了解了这些方法的参数和返回值才会懂。我大概说一下吧: 输出大于1 的时候,执行 catch 的回调函数时输出了 Done: timeout in 1.4453681319996927 seconds. 然后因为 catch 的回调函数没有返回值,所以 catch 方法返回的 promise 对象的状态变为了 'resolved',value 值变为了 undefined。由于 catch 方法返回的 promise 对象状态变为 'resolved',所以触发了then 方法的回调函数,输出了 'Failed: ' + value, 即:Failed: undefined ...... 是不是看得很糊涂,不明白的同学还是多看看官方文档吧

    • Created at July 26, 2019 11:05 AM

      Promise 无论成功或者失败都会进入then,在then中接受错误的对象后再进入的catch,所以换位子回出错。

    • Created at August 6, 2019 5:36 PM

      我理解的不知道对不对:Promise构造对象之前执行传入的方法,会携带成功或失败后的信息,并将携带的信息传递给接下来执行的then方法或者catch方法。而Promise执行完then方法或catch方法之后返回的Promise对象不再携带处理成功或失败的结果了,所以你再次调用then方法,信息是undefined。你看接下来的示例,如果想连续使用then方法,你要重新构造Promise对象传入相应处理函数然后才能返回处理结果

    • Created at March 11, 2021 10:47 AM

      特意登录 恢复 吸猫二哈 同学

      你的说法

      虽然知道原因,但我觉得我讲起来你们可能听不懂,因为要阅读文档,了解了这些方法的参数和返回值才会懂。我大概说一下吧: 输出大于1 的时候,执行 catch 的回调函数时输出了 Done: timeout in 1.4453681319996927 seconds. 然后因为 catch 的回调函数没有返回值,所以 catch 方法返回的 promise 对象的状态变为了 'resolved',value 值变为了 undefined。由于 catch 方法返回的 promise 对象状态变为 'resolved',所以触发了then 方法的回调函数,输出了 'Failed: ' + value, 即:Failed: undefined ...... 是不是看得很糊涂,不明白的同学还是多看看官方文档吧

      不对

      测试
      		<script>
      			function test(resove, reject) {
      				const random = Math.random() * 2
      				setTimeout(function() {
      					if (random < 1) {
      						console.log('call resolve')
      						resove('200 ok')
      					} else {
      						console.log('call reject')
      						reject('timeout ' + random + ' seconds')
      					}
      				}, random * 1000)
      				// if (random < 1) resove('小于一')
      				// else reject('不小于1')
      			}
      			const promise = new Promise(test)
      			promise.catch(response => {
      				console.log(promise);
      				console.log(response);
      			}).then(error => {
      				console.log(promise);
      				console.log(error);
      			})
      		</script>
      

      结果

      call reject
      test.html:26 Promise {<rejected>: "timeout 1.9567438656987801 seconds"}
      test.html:27 timeout 1.9567438656987801 seconds
      test.html:29 Promise {<rejected>: "timeout 1.9567438656987801 seconds"}
      test.html:30 undefined
      

      也是需要多看看官方文档啊

       Read More

    • Created at March 13, 2021 4:37 PM

      回复以下 庸人自扰Ray 同学

      您的代码有问题,在catch与then中调用的是同一个promise对象,而吸猫二哈所讲的catch方法返回的promise对象并不是这个对象。

      正确代码应该是

      function test(resove, reject) {
          const random = Math.random() * 2
          setTimeout(function() {
              if (random < 1) {
                  console.log('call resolve')
                  resove('200 ok')
              } else {
                  console.log('call reject')
                  reject('timeout ' + random + ' seconds')
              }
          }, random * 1000)
          // if (random < 1) resove('小于一')
          // else reject('不小于1')
      }
      const promise = new Promise(test)
      p1 = promise.catch(response => {
          console.log(promise);
          console.log(response);
      })
      p2 = p1.then(error => {
          console.log(p1);
          console.log(error);
      })
      

      而代码运行的结果为

      call reject
      VM2060:17 Promise {<rejected>: "timeout 1.8380489456267801 seconds"}
      VM2060:18 timeout 1.8380489456267801 seconds
      VM2060:21 Promise {<fulfilled>: undefined}
      VM2060:22 undefined
      

      您也需要多多看看官方文档啊

      (上述的fulfilled即为吸猫二哈说的resolved,详情请查看https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise

       Read More

    • Created at March 19, 2021 11:27 AM

      再次阅读了MDN文档,然后测试了你的代码,我想说的是,const promise = new Promise(test),这个const promise返回的只有一个状态,也就是说,只能走resove和reject之一,而catch、then代表他们的状态。我的代码想说明的是promise只能存在一个状态,另一个是不存在的,当然是undefined

    • Created at March 19, 2021 11:35 AM

      回复

      devil3lood

      catch方法返回的promise对象并不是这个对象

      这个说法也不对吧,

      p1 = promise.catch(response => {
          console.log(promise);
          console.log(response);
      })
      

      没有返回 promise啊,这里只是一个箭头函数,并没有返回任何东西.........

    • Created at March 25, 2021 7:23 PM

      回复

      庸人自扰Ray

      这和箭头函数有什么关系呢?

      我指的是promise的catch方法会返回一个新的promise对象

      按照mdn的promise页面

      我们可以用 promise.then()promise.catch() 和 promise.finally() 这些方法将进一步的操作与一个变为已敲定状态的 promise 关联起来。这些方法还会返回一个新生成的 promise 对象,这个对象可以被非强制性的用来做链式调用

      而在您最初的发言中在.then与.catch的语句中的箭头函数中始终调用的都是最初的promise对象,输出结果必然会是一样的且没有意义。

      建议您在发言之前请多多思考一下。

  • resolve和reject代表什么意思?

    吉岸齐昂 created at March 25, 2018 4:56 PM, Last updated at September 10, 2020 5:37 PM

    resolve和reject代表什么意思?

    • Created at April 2, 2018 3:19 PM

      成功与失败吧

    • Created at April 2, 2018 3:21 PM

      成功与失败的回调,调用resolve promise.then对应会调用,代表成功,调用reject对应调用promise.catch代表失败。

    • Created at June 11, 2018 5:15 PM

      这两个函数是js的ES6的api

    • Created at December 2, 2018 2:04 PM

      这两个函数由浏览器提供 调用resolve函数状态就是成功并传参数给then()内的函数 调用reject函数状态就是失败

    • Created at September 10, 2020 5:37 PM

      resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

      也就是它们有两个作用:1、改变promise状态; 2、将操作结果作为参数传出去,例如 resolve( result ), 这样后面调用then 才能直接得到 这个result,并将得到的result 作为参数用于 then 里面的函数操作

  • 情景化记忆 记笔记

    SpringShaw created at May 1, 2019 7:39 PM, Last updated at July 30, 2020 4:49 PM

    Promise().then().then....catch() 多任务串行执行.

    情景化记忆:在一个任务链中,比如我要向上级部门一层层的往上提交申请,if(某种条件)承诺帮你resolve解决问题,else承诺reject你的请求. 他给出的resolve问题的办法只是个空头Promise,then到总经理那实现具体承诺,如果总经理还是给一个空头承诺(返回Promise实例),还得then到董事长那里.... 任一一步做出的是reject的承诺,还有什么好说的,被拒绝了,后面的就不会再往上走了呀. 准备catch 拒绝通知吧blablabla

    Promise.all([p1,p2,...]) 多任务并行执行

    都要成功才进入then,返回结果数组.

    Promise.race([p1,p2,...]) 多任务赛跑.

    then()和catch(),谁先调用算谁的,其它任务中断.

  • 【浏览器】Promice总结

    用户7303966659 created at June 12, 2020 12:14 AM, Last updated at July 2, 2020 11:30 AM

    JavaScript是单线程执行的,异步的

    Promice作用:

    //串行
    
    //承诺的事 resove()返回给then  reject() 返回给catch()
    var p1 = new Promice(function(reslove,reject){
    console.log("this is promice program");
    reslove("one");
    }); 
    
    p1.then(function(a){
    console.log();
    return new promice(function(reslove,reject){
    reslove("two")
    });
    })
    .then(p2).catch(function(a){
    console.log("catch the " + a);
    });
    
    var p2 = function(a){
    console.log(a);
    return new promice(function(reslove,reject){
    if(a != 'two')
    reslove("end");
    else
    reject("failed end")
    });
    };
    
    有点晚了,明天在加
    

     Read More

    • Created at June 22, 2020 9:58 AM
      //前缀数字代表标签级别,没展开一层,级别加一
      
      < 1 Promise {<pending>}      
         2 __proto__: Promise                            //原型对象为Promise
         2 [[PromiseStatus]]: "pending"
         2 [[PromiseValue]]: undefined
      
      
      //展开
      > new Promise(function () {});
      < 1 Promise {<pending>}
        2 __proto__: Promise                          //下属方法属性
          3 catch: ƒ catch()
          3 constructor: ƒ Promise()
          3 finally: ƒ finally()
          3 then: ƒ then()
            3 Symbol(Symbol.toStringTag): "Promise"
          3 __proto__: Object[[PromiseStatus]]: "pending"
        2 [[PromiseValue]]: undefined
      
      
      原型链  Promise -> Object -> null
      

       Read More

    • Created at July 2, 2020 11:15 AM

      异步代码最早是回调函数形式(由于JavaScript是单线程,对于一些“昂贵”的操作(高耗时),如定时,ajax,事件,往往以会回调函数形式实行异步操作提高cpu利用率)

      promise专为异步代码解决复杂度 ——分离了执行代码(then)和结果处理函数(catch)

      ES7引入async和await进一步解决异步代码的复杂性

      //异步——回调函数(回调函数不一定异步)
      function callback(){
      console.log("this is callback()");
      console.log(callback()-2);
      }
      
      settime(1000,callback);
      console("before callback()");
      
      //promise
      new Promise(function(){
      console.log("this is callback()");
      }).then(function(){
      console.log("callback()-2");
      })
      
      //async await
      async function(){
      await settime(1000);
      await console.log("this is callback()");
      await console.log(callback()-2);
      }
      console.log("before callback()");
      

       Read More

    • Created at July 2, 2020 11:30 AM

      上面的回调函数例子举的不太行

      上面的是高耗时导致该操作挂起,执行下一操作

      回调函数一般用于事件中 onclick(function) 或者ajax这样昂贵的操作(setTime()可以模拟这样的操作)

    • then( function )串行执行任务,代码可读性强 catch( function )

    • all( array )模拟并行执行任务

    • rece( array )执行响应时间短的,其他丢弃

  • Promise

    命运这种东西生来就该被踩在脚下 created at June 11, 2020 2:17 AM, Last updated at June 11, 2020 2:17 AM

    大佬,讲得很好,三个例子都很棒,感谢!但第一遍看着有点没明白,您可以考虑把setTimeout函数的介绍以及自己定义的log函数顺序放前面一点,那就更完美了。:-)

  • 第二遍终于明白一些了。。

    善良的心比黄金重要 created at May 7, 2020 10:47 AM, Last updated at May 7, 2020 10:47 AM

    感觉 js 和 C++ 差别还是很大呀。。

  • 不知道Log是什么意思

    倩宝儿o_O created at March 8, 2018 10:59 AM, Last updated at December 10, 2019 1:42 PM

    不明白log是什么意思呢,执行之后显示未定义

    • Created at March 8, 2018 2:02 PM

      看到啦,哈哈哈哈

    • Created at July 30, 2018 6:47 PM

      啥意思?同问

    • Created at August 13, 2018 9:52 AM

      应该是漏写了console. 这句话的目的就是打印日志:console.log

    • Created at August 13, 2018 3:30 PM

      当需要写大量console.log的时候,我也喜欢弄一个全局方法简化console.log 例如:

      function log(s){ 
          console.log(s);
      }
      
    • Created at October 30, 2018 9:23 PM

      function log(s) { var p = document.createElement('p'); p.innerHTML = s; logging.appendChild(p); } var log = document.getElementById('test-promise-ajax-result');

      //两种,log是上文定义函数或者标签变量

    • Created at August 12, 2019 11:37 PM

      在这个页面看到第一个log的时候,我也懵逼,甚至去查一下这个单独的log是什么函数;直到我看后文,发现一个定义log的函数......

    • Created at November 13, 2019 3:35 PM

      {log} = console;

      解决

    • Created at December 10, 2019 1:42 PM

      log不是上面定义的一个方法嘛?

  • 客观评价

    未来有妮和我 created at August 22, 2019 4:33 PM, Last updated at August 22, 2019 4:33 PM

    文件处理、ajax、promise都讲的不是很清晰。可能代码演示比较好表达一点吧。廖神码字还是扯不清楚。

  • 扩展阅读

    思想上的小丸子 created at April 12, 2019 2:58 PM, Last updated at April 12, 2019 2:58 PM

    看得一头雾水,扩展阅读 http://es6.ruanyifeng.com/#docs/promise ,能了解一些基本信息,再来看可能更好理解一些~

  • 既然JS是单线程的,那是如何完成所谓的并行任务的呢?

    Exmlyshy created at February 26, 2019 3:16 PM, Last updated at February 26, 2019 3:16 PM

    经找资料后自己的理解:JS引擎是单线程的,但是浏览器是多线程的,其执行的方法如setTimeOut是由浏览器来调度的,计时器也是一个单独的线程(并不是JS引擎来计时)。而Promise.all(iterable) 方法返回一个 Promise 实例,其内部方法串行执行,比如P1先计时完成,浏览器的触发线程就将P1方法放到JS队列中由JS引擎来执行。

  • 既然JS是单线程,那么Promise.all是如何实现并行执行的?

    涛了个涛嘿 created at December 19, 2018 10:06 AM, Last updated at February 26, 2019 3:14 PM

    既然JS是单线程,那么Promise.all是如何实现并行执行的?

    • Created at February 26, 2019 3:14 PM

      JS引擎是单线程的,但是浏览器是多线程的,其执行的方法如setTimeOut是由浏览器来调度的,计时器也是一个单独的线程(并不是JS引擎来计时)。而Promise.all(iterable) 方法返回一个 Promise 实例,其内部方法串行执行,比如P1先计时完成,浏览器的触发线程就将P1方法放到JS队列中由JS引擎来执行。

  • node

    我是怪物1981 created at November 22, 2018 9:12 AM, Last updated at November 22, 2018 9:12 AM

    function promise (URL) { let resdfile = new Promise(function (resolve,reject) { fs.readFile(URL,function (err,data) { if (err){ reject(err) } if (data){ resolve(data) } }) }) return resdfile }

    promise("testa.txt").then(function (data) { console.log("done:"+data) return promise("test.txt") }).then(function (data) { console.log("done:"+data) }).catch(function (err) { console.log("fail:"+err) })

    • Created at November 22, 2018 9:12 AM

      function promise (URL) { return new Promise((resolve,reject)=>{ fs.readFile(URL,(err,data)=>{ err?reject(err):resolve(data) })}) }

      再省一点点

  • Promise其实是Monad在JavaScript中的应用

    Swiftyxy13 created at November 1, 2018 3:23 PM, Last updated at November 1, 2018 3:23 PM
  • 可不可能promise对象在new出来之后到调用then()方法之前的这段时间内,异步方法就已经执行结束了?如果可能的话,这段时间里调用resolve方法岂不是会报错(因为还没来得及调用then()方法而未得到赋值)?

  • setTimeout(resolve, 500, 'P1')为什么要这么写呢

    十八年后 created at March 6, 2018 10:39 AM, Last updated at October 26, 2018 9:33 AM

    setTimeout(resolve, 500, 'P1') 之前学setTimeout的时候只有两个参数,一个函数一个延迟时间;这里三个参数代表什么,为什么要这么写? resolve在这里代表的是成功的状态吗?‘P1’返回值为什么要写到时间的后面?

    • Created at March 27, 2018 11:53 AM

      是resolve函数的参数

    • Created at September 29, 2018 4:15 PM

      参数还可以这么写吗?我刚就在想每次then链式调用的时候参数是在哪传过去的?但是setTimeout里边传进去的,难道是封装过setTimeout了吗?

    • Created at October 26, 2018 9:33 AM

      setTimeout(function, milliseconds, param1, param2, ...) param1, param2, ... 可选。 传给执行函数的其他参数(IE9 及其更早版本不支持该参数)。

  • 不明白这个表述

    请输入昵称yy created at May 31, 2018 1:58 PM, Last updated at August 13, 2018 5:01 PM

    job1.then(job2).then(job3).catch(handleError); 其中,job1、job2和job3都是Promise对象。 不明白 我觉得job1是Promise对象,job2,3应该是异步函数

    • Created at June 11, 2018 5:17 PM

      job2 job3 不是Promise对象,后面的then和cathch怎么执行

    • Created at June 11, 2018 11:46 PM

      job2 job3也要有承諾(為Promise對象) 如果他們之間沒有共同承諾 光只有job1單方面承諾也是沒有用的

      男方我願意 女方拒絕 總不能強著來

    • Created at June 13, 2018 7:24 AM

      楼主的猜测是对的,文中表述不太严谨,廖大偶尔会手滑. 2楼3楼两位朋友太迷信,不是学习的正确态度.

      var job2=function (r) {
          log('Done: ' + r);
      };
      var job3=function (reason) {
          log('Failed: ' + reason);
      };
      
      var job1 = new Promise(function (resolve, reject) {
          log('start new Promise...');
          var timeOut = Math.random() * 2;
          log('set timeout to: ' + timeOut + ' seconds.');
          setTimeout(function () {
              if (timeOut < 1) {
                  log('call resolve()...');
                  resolve('200 OK');
              }
              else {
                  log('call reject()...');
                  reject('timeout in ' + timeOut + ' seconds.');
              }
          }, timeOut * 1000);
      }).then(job2).catch(job3);
      console.log(job1 instanceof Promise);
      console.log(typeof(job1));
      //console.log(typeof(job1.then(job2)));
      console.log(typeof(job2));
      console.log(job2 instanceof Promise);
      //console.log(typeof(job1.then(job3)));
      console.log(typeof(job3));
      console.log(job3 instanceof Promise);
      

      用廖大自己的示例演示一下,job2,job3type是function,job1的type是object. job1.then(job2) 这个表达式才返回一个Promise,链式就得这样才玩得下去. 看见job1是Promise,就想当然地认为job2,job3也是promise,这是被廖大忽悠瘸了.

       Read More

    • Created at June 21, 2018 5:40 PM

      .then(job2)和.then(job3)就是异步函数,他们返回的是Promise对象,即job2,job3

    • Created at June 24, 2018 3:23 PM

      我觉得这是链式调用, job2和job3当然也返回promise, 因为参数只有resolve, 所以会一直成功, 会一直沿着链执行下去

    • Created at August 13, 2018 5:01 PM

      老师不是讲语法,不是说传什么类型参数,所以老师讲的没错,要从结果的角度去看,而不是从传参来角度去看。

      没错,参数的确是个函数,但实质内容(即函数执行结果)是个promise对象。

  • Timeout*1000干嘛用的

    Demo_达子 created at May 30, 2018 10:58 PM, Last updated at August 13, 2018 3:25 PM

    timeout*1000是啥

  • 发表评论



    来自  https://www.liaoxuefeng.com/wiki/1022910821149312/1023024413276544


    普通分类: