Promise必备知识汇总和面试情况

发表于 3年以前  | 总阅读数:217 次

写在前面

Javascript异步编程先后经历了四个阶段,分别是Callback阶段,Promise阶段,Generator阶段和Async/Await阶段。Callback很快就被发现存在回调地狱和控制权问题,Promise就是在这个时间出现,用以解决这些问题,Promise并非一个新事务,而是按照一个规范实现的类,这个规范有很多,如 Promise/APromise/BPromise/D以及 Promise/A 的升级版 Promise/A+,最终 ES6 中采用了 Promise/A+ 规范。后来出现的Generator函数以及Async函数也是以Promise为基础的进一步封装,可见Promise在异步编程中的重要性。

关于Promise的资料已经很多,但每个人理解都不一样,不同的思路也会有不一样的收获。这篇文章会着重写一下Promise的实现以及笔者在日常使用过程中的一些心得体会。

实现Promise

规范解读

Promise/A+规范主要分为术语、要求和注意事项三个部分,我们重点看一下第二部分也就是要求部分,以笔者的理解大概说明一下,具体细节参照完整版Promise/A+标准。

1、Promise有三种状态pendingfulfilledrejected。(为了一致性,此文章称fulfilled状态为resolved状态)

  • 状态转换只能是pendingresolved或者pendingrejected
  • 状态一旦转换完成,不能再次转换。

2、Promise拥有一个then方法,用以处理resolvedrejected状态下的值。

  • then方法接收两个参数onFulfilledonRejected,这两个参数变量类型是函数,如果不是函数将会被忽略,并且这两个参数都是可选的。
  • then方法必须返回一个新的promise,记作promise2,这也就保证了then方法可以在同一个promise上多次调用。(ps:规范只要求返回promise,并没有明确要求返回一个新的promise,这里为了跟ES6实现保持一致,我们也返回一个新promise
  • onResolved/onRejected有返回值则把返回值定义为x,并执行[[Resolve]](promise2, x);
  • onResolved/onRejected运行出错,则把promise2设置为rejected状态;
  • onResolved/onRejected不是函数,则需要把promise1的状态传递下去。

3、不同的promise实现可以的交互。

  • 规范中称这一步操作为promise解决过程,函数标示为[[Resolve]](promise, x),promise为要返回的新promise对象,xonResolved/onRejected的返回值。如果xthen方法且看上去像一个promise,我们就把x当成一个promise的对象,即thenable对象,这种情况下尝试让promise接收x的状态。如果x不是thenable对象,就用x的值来执行 promise
  • [[Resolve]](promise, x)函数具体运行规则:
  • 如果 promisex 指向同一对象,以 TypeError 为据因拒绝执行 promise;
  • 如果 xPromise ,则使 promise 接受 x 的状态;
  • 如果 x 为对象或者函数,取x.then的值,如果取值时出现错误,则让promise进入rejected状态,如果then不是函数,说明x不是thenable对象,直接以x的值resolve,如果then存在并且为函数,则把x作为then函数的作用域this调用,then方法接收两个参数,resolvePromiserejectPromise,如果resolvePromise被执行,则以resolvePromise的参数value作为x继续调用[[Resolve]](promise, value),直到x不是对象或者函数,如果rejectPromise被执行则让promise进入rejected状态;
  • 如果 x 不是对象或者函数,直接就用x的值来执行promise

代码实现

规范解读第1条,代码实现:

class Promise {
  // 定义Promise状态,初始值为pending
  status = 'pending';
  // 状态转换时携带的值,因为在then方法中需要处理Promise成功或失败时的值,所以需要一个全局变量存储这个值
  data = '';

  // Promise构造函数,传入参数为一个可执行的函数
  constructor(executor) {
    // resolve函数负责把状态转换为resolved
    function resolve(value) {
      this.status = 'resolved';
      this.data = value;
    }
    // reject函数负责把状态转换为rejected
    function reject(reason) {
      this.status = 'rejected';
      this.data = reason;
    }

    // 直接执行executor函数,参数为处理函数resolve, reject。因为executor执行过程有可能会出错,错误情况需要执行reject
    try {
      executor(resolve, reject);
    } catch(e) {
      reject(e)
    }
  }
}

第1条就是实现完毕了,相对简单,配合代码注释很容易理解。

规范解读第2条,代码实现:

  /**
    * 拥有一个then方法
    * then方法提供:状态为resolved时的回调函数onResolved,状态为rejected时的回调函数onRejected
    * 返回一个新的Promise
  */
  then(onResolved, onRejected) {
    // 设置then的默认参数,默认参数实现Promise的值的穿透
    onResolved = typeof onResolved === 'function' ? onResolved : function(v) { return e };
    onRejected = typeof onRejected === 'function' ? onRejected : function(e) { throw e };

    let promise2;

    promise2 =  new Promise((resolve, reject) => {
      // 如果状态为resolved,则执行onResolved
      if (this.status === 'resolved') {
        try {
          // onResolved/onRejected有返回值则把返回值定义为x
          const x = onResolved(this.data);
          // 执行[[Resolve]](promise2, x)
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      }
      // 如果状态为rejected,则执行onRejected
      if (this.status === 'rejected') {
        try {
          const x = onRejected(this.data);
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      }
    });

    return promise2;
  }

现在我们就按照规范解读第2条,实现了上述代码,上述代码很明显是有问题的,问题如下

  1. resolvePromise未定义;
  2. then方法执行的时候,promise可能仍然处于pending状态,因为executor中可能存在异步操作(实际情况大部分为异步操作),这样就导致onResolved/onRejected失去了执行时机;
  3. onResolved/onRejected这两个函数需要异步调用(官方Promise实现的回调函数总是异步调用的)。

解决办法:

  1. 根据规范解读第3条,定义并实现resolvePromise函数;
  2. then方法执行时如果promise仍然处于pending状态,则把处理函数进行储存,等resolve/reject函数真正执行的的时候再调用。
  3. promise.then属于微任务,这里我们为了方便,用宏任务setTiemout来代替实现异步,具体细节特别推荐[这篇文章] 。

好了,有了解决办法,我们就把代码进一步完善:

class Promise {
  // 定义Promise状态变量,初始值为pending
  status = 'pending';
  // 因为在then方法中需要处理Promise成功或失败时的值,所以需要一个全局变量存储这个值
  data = '';
  // Promise resolve时的回调函数集
  onResolvedCallback = [];
  // Promise reject时的回调函数集
  onRejectedCallback = [];

  // Promise构造函数,传入参数为一个可执行的函数
  constructor(executor) {
    // resolve函数负责把状态转换为resolved
    function resolve(value) {
      this.status = 'resolved';
      this.data = value;
      for (const func of this.onResolvedCallback) {
        func(this.data);
      }
    }
    // reject函数负责把状态转换为rejected
    function reject(reason) {
      this.status = 'rejected';
      this.data = reason;
      for (const func of this.onRejectedCallback) {
        func(this.data);
      }
    }

    // 直接执行executor函数,参数为处理函数resolve, reject。因为executor执行过程有可能会出错,错误情况需要执行reject
    try {
      executor(resolve, reject);
    } catch(e) {
      reject(e)
    }
  }
  /**
    * 拥有一个then方法
    * then方法提供:状态为resolved时的回调函数onResolved,状态为rejected时的回调函数onRejected
    * 返回一个新的Promise
  */
  then(onResolved, onRejected) {

    // 设置then的默认参数,默认参数实现Promise的值的穿透
    onResolved = typeof onResolved === 'function' ? onResolved : function(v) { return e };
    onRejected = typeof onRejected === 'function' ? onRejected : function(e) { throw e };

    let promise2;

    promise2 =  new Promise((resolve, reject) => {
      // 如果状态为resolved,则执行onResolved
      if (this.status === 'resolved') {
        setTimeout(() => {
          try {
            // onResolved/onRejected有返回值则把返回值定义为x
            const x = onResolved(this.data);
            // 执行[[Resolve]](promise2, x)
            this.resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      }
      // 如果状态为rejected,则执行onRejected
      if (this.status === 'rejected') {
        setTimeout(() => {
          try {
            const x = onRejected(this.data);
            this.resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      }
      // 如果状态为pending,则把处理函数进行存储
      if (this.status = 'pending') {
        this.onResolvedCallback.push(() => {
          setTimeout(() => {
            try {
              const x = onResolved(this.data);
              this.resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          }, 0);
        });

        this.onRejectedCallback.push(() => {
          setTimeout(() => {
            try {
              const x = onRejected(this.data);
              this.resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          }, 0);
        });
      }

    });

    return promise2;
  }

  // [[Resolve]](promise2, x)函数
  resolvePromise(promise2, x, resolve, reject) {

  }

}

至此,规范中关于then的部分就全部实现完毕了。代码添加了详细的注释,参考注释不难理解。

规范解读第3条,代码实现:

// [[Resolve]](promise2, x)函数
  resolvePromise(promise2, x, resolve, reject) {
    let called = false;

    if (promise2 === x) {
      return reject(new TypeError('Chaining cycle detected for promise!'))
    }

    // 如果x仍然为Promise的情况
    if (x instanceof Promise) {
      // 如果x的状态还没有确定,那么它是有可能被一个thenable决定最终状态和值,所以需要继续调用resolvePromise
      if (x.status === 'pending') {
        x.then(function(value) {
          resolvePromise(promise2, value, resolve, reject)
        }, reject)
      } else { 
        // 如果x状态已经确定了,直接取它的状态
        x.then(resolve, reject)
      }
      return
    }

    if (x !== null && (Object.prototype.toString(x) === '[object Object]' || Object.prototype.toString(x) === '[object Function]')) {
      try {
        // 因为x.then有可能是一个getter,这种情况下多次读取就有可能产生副作用,所以通过变量called进行控制
        const then = x.then 
        // then是函数,那就说明x是thenable,继续执行resolvePromise函数,直到x为普通值
        if (typeof then === 'function') { 
          then.call(x, (y) => { 
            if (called) return;
            called = true;
            this.resolvePromise(promise2, y, resolve, reject);
          }, (r) => {
            if (called) return;
            called = true;
            reject(r);
          })
        } else { // 如果then不是函数,那就说明x不是thenable,直接resolve x
          if (called) return ;
          called = true;
          resolve(x);
        }
      } catch (e) {
        if (called) return;
        called = true;
        reject(e);
      }
    } else {
      resolve(x);
    }
  }

这一步骤非常简单,只要按照规范转换成代码即可。

最后,完整的Promise按照规范就实现完毕了,是的,规范里并没有规定catchPromise.resolvePromise.rejectPromise.all等方法,接下来,我们就看一看Promise的这些常用方法。

Promise其他方法实现

1、catch方法

catch方法是对then方法的封装,只用于接收reject(reason)中的错误信息。因为在then方法中onRejected参数是可不传的,不传的情况下,错误信息会依次往后传递,直到有onRejected函数接收为止,因此在写promise链式调用的时候,then方法不传onRejected函数,只需要在最末尾加一个catch()就可以了,这样在该链条中的promise发生的错误都会被最后的catch捕获到。

  catch(onRejected) {
    return this.then(null, onRejected);
  }
2、done方法

catchpromise链式调用的末尾调用,用于捕获链条中的错误信息,但是catch方法内部也可能出现错误,所以有些promise实现中增加了一个方法donedone相当于提供了一个不会出错的catch方法,并且不再返回一个promise,一般用来结束一个promise链。

 done() {
    this.catch(reason => {
      console.log('done', reason);
      throw reason;
    });
  }
3、finally方法

finally方法用于无论是resolve还是rejectfinally的参数函数都会被执行。

  finally(fn) {
    return this.then(value => {
      fn();
      return value;
    }, reason => {
      fn();
      throw reason;
    });
  };
4、Promise.all方法

Promise.all方法接收一个promise数组,返回一个新promise2,并发执行数组中的全部promise,所有promise状态都为resolved时,promise2状态为resolved并返回全部promise结果,结果顺序和promise数组顺序一致。如果有一个promiserejected状态,则整个promise2进入rejected状态。

  static all(promiseList) {
    return new Promise((resolve, reject) => {
      const result = [];
      let i = 0;
      for (const p of promiseList) {
        p.then(value => {
          result[i] = value;
          if (result.length === promiseList.length) {
            resolve(result);
          }
        }, reject);
        i++;
      }
    });
  }
5、Promise.race方法

Promise.race方法接收一个promise数组, 返回一个新promise2,顺序执行数组中的promise,有一个promise状态确定,promise2状态即确定,并且同这个promise的状态一致。

 static race(promiseList) {
    return new Promise((resolve, reject) => {
      for (const p of promiseList) {
        p.then((value) => {
          resolve(value);   
        }, reject);
      }
    });
  }
6、Promise.resolve方法/Promise.reject

Promise.resolve用来生成一个rejected完成态的promisePromise.reject用来生成一个rejected失败态的promise

  static resolve(value) {
    let promise;

    promise = new Promise((resolve, reject) => {
      this.resolvePromise(promise, value, resolve, reject);
    });

    return promise;
  }

  static reject(reason) {
    return new Promise((resolve, reject) => {
      reject(reason);
    });
  }

常用的方法基本就这些,Promise还有很多扩展方法,这里就不一一展示,基本上都是对then方法的进一步封装,只要你的then方法没有问题,其他方法就都可以依赖then方法实现。

Promise面试相关

面试相关问题,笔者只说一下我司这几年的情况,并不能代表全部情况,参考即可。Promise是我司前端开发职位,nodejs开发职位,全栈开发职位,必问的一个知识点,主要问题会分布在Promise介绍、基础使用方法以及深层次的理解三个方面,问题一般在3-5个,根据面试者回答情况会适当增减。

1、简单介绍下Promise。

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。(当然了也可以简单介绍promise状态,有什么方法,callback存在什么问题等等,这个问题是比较开放的)

  • 提问概率:99%
  • 评分标准:人性化判断即可,此问题一般作为引入问题。
  • 加分项:熟练说出Promise具体解决了那些问题,存在什么缺点,应用方向等等。
2、实现一个简单的,支持异步链式调用的Promise类。

这个答案不是固定的,可以参考最简实现 Promise,支持异步链式调用

  • 提问概率:50%(手撸代码题,因为这类题目比较耗费时间,一场面试并不会出现很多,所以出现频率不是很高,但却是必备知识)
  • 加分项:基本功能实现的基础上有onResolved/onRejected函数异步调用,错误捕获合理等亮点。
3、Promise.then在Event Loop中的执行顺序。(可以直接问,也可以出具体题目让面试者回答打印顺序)

JS中分为两种任务类型:macrotaskmicrotask,其中macrotask包含:主代码块,setTimeoutsetIntervalsetImmediate等(setImmediate规定:在下一次Event Loop(宏任务)时触发);microtask包含:Promiseprocess.nextTick等(在node环境下,process.nextTick的优先级高于PromiseEvent Loop中执行一个macrotask任务(栈中没有就从事件队列中获取)执行过程中如果遇到microtask任务,就将它添加到微任务的任务队列中,macrotask任务执行完毕后,立即执行当前微任务队列中的所有microtask任务(依次执行),然后开始下一个macrotask任务(从事件队列中获取) 浏览器运行机制可参考[这篇文章]

  • 提问概率:75%(可以理解为4次面试中3次会问到,顺便可以考察面试者对JS运行机制的理解)
  • 加分项:扩展讲述浏览器运行机制。
4、阐述Promise的一些静态方法。

Promise.deferredPromise.allPromise.racePromise.resolvePromise.reject

  • 提问概率:25%(相对基础的问题,一般在其他问题回答不是很理想的情况下提问,或者为了引出下一个题目而提问)
  • 加分项:越多越好
5、Promise存在哪些缺点。

1、无法取消Promise,一旦新建它就会立即执行,无法中途取消。2、如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。3、吞掉错误或异常,错误只能顺序处理,即便在Promise链最后添加catch方法,依然可能存在无法捕捉的错误(catch内部可能会出现错误) 4、阅读代码不是一眼可以看懂,你只会看到一堆then,必须自己在then的回调函数里面理清逻辑。

  • 提问概率:25%(此问题作为提高题目,出现概率不高)
  • 加分项:越多越合理越好(网上有很多说法,不一一佐证) (此题目,欢迎大家补充答案)
6、使用Promise进行顺序(sequence)处理。

1、使用async函数配合await或者使用generator函数配合yield。2、使用promise.then通过for循环或者Array.prototype.reduce实现。

function sequenceTasks(tasks) {
    function recordValue(results, value) {
        results.push(value);
        return results;
    }
    var pushValue = recordValue.bind(null, []);
    return tasks.reduce(function (promise, task) {
        return promise.then(() => task).then(pushValue);
    }, Promise.resolve());
}
  • 提问概率:90%(我司提问概率极高的题目,即能考察面试者对promise的理解程度,又能考察编程逻辑,最后还有bindreduce等方法的运用)
  • 评分标准:说出任意解决方法即可,其中只能说出async函数和generator函数的可以得到20%的分数,可以用promise.then配合for循环解决的可以得到60%的分数,配合Array.prototype.reduce实现的可以得到最后的20%分数。
7、如何停止一个Promise链?

在要停止的promise链位置添加一个方法,返回一个永远不执行resolve或者rejectPromise,那么这个promise永远处于pending状态,所以永远也不会向下执行thencatch了。这样我们就停止了一个promise链。

   Promise.cancel = Promise.stop = function() {
      return new Promise(function(){})
    }
  • 提问概率:50%(此问题主要考察面试者罗辑思维) (此题目,欢迎大家补充答案)
8、Promise链上返回的最后一个Promise出错了怎么办?

catchpromise链式调用的末尾调用,用于捕获链条中的错误信息,但是catch方法内部也可能出现错误,所以有些promise实现中增加了一个方法donedone相当于提供了一个不会出错的catch方法,并且不再返回一个promise,一般用来结束一个promise链。

  done() {
    this.catch(reason => {
      console.log('done', reason);
      throw reason;
    });
  }
  • 提问概率:90%(同样作为出题率极高的一个题目,充分考察面试者对promise的理解程度)
  • 加分项:给出具体的done()方法代码实现
9、Promise存在哪些使用技巧或者最佳实践?

1、链式promise要返回一个promise,而不只是构造一个promise。2、合理的使用Promise.allPromise.race等方法。3、在写promise链式调用的时候,then方法不传onRejected函数,只需要在最末尾加一个catch()就可以了,这样在该链条中的promise发生的错误都会被最后的catch捕获到。如果catch()代码有出现错误的可能,需要在链式调用的末尾增加done()函数。

  • 提问概率:10%(出题概率极低的一个题目)
  • 加分项:越多越好

(此题目,欢迎大家补充答案)

至此,我司关于Promise的一些面试题目就列举完毕了,有些题目的答案是开放的,欢迎大家一起补充完善。总结起来,Promise作为js面试必问部分还是相对容易掌握并通过的。

总结

Promise作为所有js开发者的必备技能,其实现思路值得所有人学习,通过这篇文章,希望小伙伴们在以后编码过程中能更加熟练、更加明白的使用Promise。

本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/3Hr_2M-0UBGQk26mIIMeFQ

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237231次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8065次阅读
 目录